79

作为一个新的 .NET 3.5 程序员,我开始学习 LINQ,我发现了一些我以前没有注意到的非常基本的东西:

这本书声称每个数组都实现IEnumerable<T>了(显然,否则我们不能使用 LINQ 到数组上的对象......)。当我看到这个时,我想我从来没有真正想过这个问题,我问自己所有数组还实现了什么——所以我 System.Array使用对象浏览器进行了检查(因为它是 CLR 中每个数组的基类),并且,令我惊讶的是,它没有实现IEnumerable<T>

所以我的问题是:定义在哪里?我的意思是,我怎样才能准确地知道每个数组实现了哪些接口?

4

5 回答 5

81

文档(强调我的):

[...] Array 类实现了System.Collections.Generic.IList<T>System.Collections.Generic.ICollection<T>System.Collections.Generic.IEnumerable<T>泛型接口。这些实现在运行时提供给数组,因此对文档构建工具不可见。

编辑:正如 Jb Evain 在他的评论中指出的那样,只有向量(一维数组)实现了通用接口。至于为什么多维数组不实现泛型接口,我不太确定,因为它们确实实现了非泛型对应物(参见下面的类声明)。

该类System.Array(即每个数组)也实现了这些非泛型接口:

public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable
于 2010-12-19T10:42:19.140 回答
74

您可以使用一个小代码片段凭经验找到问题的答案:

foreach (var type in (new int[0]).GetType().GetInterfaces())
    Console.WriteLine(type);

运行上面的代码片段将产生以下输出(on .NET 4.0):

System.ICloneable
System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]

`1意思<T>

.NET 4.5.NET Standard 1.0和之后)之后,有两个额外的接口:

System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]
于 2010-12-19T11:18:00.033 回答
57

.NET 4.5 开始,数组还实现了接口System.Collections.Generic.IReadOnlyList<T>System.Collections.Generic.IReadOnlyCollection<T>.

因此,当使用 .NET 4.5 时,由数组实现的接口的完整列表变为(使用Hosam Aly 的答案中提供的方法获得):

System.Collections.IList
System.Collections.ICollection
System.Collections.IEnumerable
System.Collections.IStructuralComparable
System.Collections.IStructuralEquatable
System.Collections.Generic.IList`1[System.Int32]
System.Collections.Generic.ICollection`1[System.Int32]
System.Collections.Generic.IEnumerable`1[System.Int32]
System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]

奇怪的是,好像忘记更新MSDN上的文档提到这两个接口了。

于 2013-08-04T11:24:13.120 回答
1

小心地在数组接口上,他们可能会实现它们,但实际上他们并没有真正做到这一点……看看下面的代码:

            var x = new int[] { 1, 2, 3, 4, 5 };
        var y = x as IList<int>;
        Console.WriteLine("The IList:" + string.Join(",", y));
        try
        {
            y.RemoveAt(1);
        }
        catch (Exception e)
        {
            Console.WriteLine(e);
        }
        Console.WriteLine(string.Join(",", y));

它产生以下输出: 结果

所以解析工作但并非所有内容都受支持,这从固定长度集合的角度来看是正确的,但如果你真的相信它是一个列表,那就大错特错了。来自 SOLID 的 Liskov 原则 :(。

对于快速测试,这将有所帮助。

于 2018-01-23T13:58:17.180 回答
0

我在 ArrayIList<T>, ICollection<T>, IEnumerable<T>SZArrayHelper嵌套类中找到了 的实现。

但我必须警告你——在那里你会发现更多的问题......

参考

之后我只有一个 - there_is_no_array ;)

于 2018-04-03T14:59:18.770 回答