List <t>构造函数(IEnumerable <t>)不接受从Array.CreateInstance(Type,Int32)创建的数组</t> </t>

时间:2014-10-07 18:25:23

标签: c# .net arrays

我是编程和.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.ArrayIEnumerable。不仅因为它在引用中,而且因为使用[]构造函数语法的第一个示例工作正常。

那么这里的问题是什么? Array.CreateInstance以某种方式设法创建一个不是IEnumerable的数组吗?

3 个答案:

答案 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再举一个例子。