我是编程和.net的新手,我很难理解为什么使用List<T>(IEnumerable<T>)
构造函数接受使用[]
创建的数组,但不接受使用Array.CreateInstance(Type, Int32)
。
这是有效的:
DirectoryInfo[] dirsArray = foo.GetDirectories();
List<DirectoryInfo> dirsList = new List<DirectoryInfo>(dirsArray);
以下是没有的:
Array dirsArray = Array.CreateInstance(typeof(DirectoryInfo), 10); //assume we know 10 is the required length
List<DirectoryInfo> dirsList = new List<DirectoryInfo>(dirsArray);
上面给出了以下编译器错误:
Error 1 The best overloaded method match for 'System.Collections.Generic.List<System.IO.DirectoryInfo>.List(System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo>)' has some invalid arguments
Error 2 Argument 1: cannot convert from 'System.Array' to 'System.Collections.Generic.IEnumerable<System.IO.DirectoryInfo>'
但我知道List<T>(IEnumerable<T>)
可以接受任何IEnumerable
作为参数。我知道System.Array
是IEnumerable
。不仅因为它在引用中,而且因为使用[]
构造函数语法的第一个示例工作正常。
那么这里的问题是什么? Array.CreateInstance
以某种方式设法创建一个不是IEnumerable
的数组吗?
答案 0 :(得分:5)
Array
类本身不是IEnumerable<T>
。您需要投射Array.CreateInstance
var dirsArray = (DirectoryInfo[]) Array.CreateInstance(typeof(DirectoryInfo), 10);
Array
是所有数组类型的基类,并且在运行时提供IEnumerable<T>
的实现。因此在编译时不能将数组用作IEnumerable<T>
。 MSDN
从.NET Framework 2.0开始,Array类实现
System.Collections.Generic.IList<T>
,System.Collections.Generic.ICollection<T>
和System.Collections.Generic.IEnumerable<T>
通用接口。 实现在运行时提供给数组,因此,通用接口不会出现在Array类的声明语法中。
答案 1 :(得分:2)
因为Array.CreateInstance(Type, Int32)
未返回IEnumerable<T>
实例,所以它返回Array
个对象。如果使用[]创建数组,则它将是IEnumerable<T>
。
请看一下这个帖子,这很简单:Why isn't Array a generic type?
答案 2 :(得分:1)
Array.CreateInstance
会返回一个无类型Array,正如您将注意到的那样,IEnumerable<T>
没有实现(它不是通用的),因此不能与{{1}一起使用构造函数。
但是,List<T>
的实际返回内容是键入的,您只需将其转换为所需的类型(所有类型的数组都派生自基类Array.CreateInstance
类)。所以你可以这样做:
Array
它应该编译。
那就是说,我从来没有找到使用List<DirectoryInfo> dirsList = new List<DirectoryInfo>((DirectoryInfo[])dirsArray);
的理由。
更新:由于在原始问题的评论中您谈到了将Array.CreateInstance
转换为ControlCollection
,因此应注意您无法转换{ {1}}到一个类型化的数组。所以这样的事情不起作用:
List<Control>
因为ControlCollection
(以及框架中的许多较旧的,先前的泛型,集合)并非来自var lst = (Control[])myControlCollection;
。在这种情况下,由于ControlCollection
实现Array
,您可以使用Cast扩展方法:
ControlCollection
如果它们实现IEnumerable
,您可以将这个技巧与框架中的许多集合类一起使用。 MatchCollection再举一个例子。