所有数组在 C # 中实现的接口是什么?

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

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

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

33506 次浏览

From the documentation (emphasis mine):

[...] the Array class implements the System.Collections.Generic.IList<T>, System.Collections.Generic.ICollection<T>, and System.Collections.Generic.IEnumerable<T> generic interfaces. The implementations are provided to arrays at run time, and therefore are not visible to the documentation build tools.

EDIT: as Jb Evain points out in his comment, only vectors (one-dimensional arrays) implement the generic interfaces. As to why multi-dimensional arrays don't implement the generic interfaces, I'm not quite sure since they do implement the non-generic counterparts (see the class declaration below).

The System.Array class (i.e. every array) also implements these non-generic interfaces:

public abstract class Array : ICloneable, IList, ICollection, IEnumerable, IStructuralComparable, IStructuralEquatable

You can find the answer to your question empirically using a small code snippet:

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

Running the above snippet would result in the following output (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 means <T>)

After .NET 4.5 (.NET Standard 1.0 and later), there's two additional interfaces:

System.Collections.Generic.IReadOnlyList`1[System.Int32]
System.Collections.Generic.IReadOnlyCollection`1[System.Int32]

Starting with .NET 4.5, arrays also implement the interfaces System.Collections.Generic.IReadOnlyList<T> and System.Collections.Generic.IReadOnlyCollection<T>.

Thus, when using .NET 4.5, the complete list of interfaces implemented by arrays becomes (obtained using the method presented in Hosam Aly's answer):

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]

Strangely, it seems that it was forgotten to update the documentation on MSDN to mention these two interfaces.

Carefully on array interfaces, they may implement them but actually they don't really do this... Take a loon on the following code:

            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));

It produces the following output: result

So parsing works but not everything is supported which is correct from fixed length collection perspective but quite wrong if you really believe that it is a list. There goes Liskov principle from SOLID :(.

For testing fast this will help.

I have found the implementation of the IList<T>, ICollection<T>, IEnumerable<T> in the SZArrayHelper nested class of the Array.

But i have to warn you - there you will find much more questions...

The refference

After that i got only one - there_is_no_array ;)