如何在没有在C#中实现属性"Count"的情况下实现IList <T>?

Ger*_*rit 25 c# arrays list

很长一段时间我都对以下内容感到好奇:

int[] array = new int[1];
int iArrayLength = array.Length;    //1
Run Code Online (Sandbox Code Playgroud)

由于数组实现了IList接口,因此允许以下内容:

int iArrayCount = ((IList<int>)array).Count;    //still 1
Run Code Online (Sandbox Code Playgroud)

但:

int iArrayCount = array.Count;  //Compile error. WHY?
int iArrayLength = array.Length;    //This is what we learned at school!
Run Code Online (Sandbox Code Playgroud)

问题:如何IList<T>在不允许在基类上使用数组的情况下实现(特别是int Count { get; }属性IList<T>)?

pho*_*oog 31

这称为显式接口成员实现.接口成员不作为该类型的公共成员公开,但可以通过转换对接口类型的引用来实现.

这可以在C#中完成,如下所示:

interface I
{
    void M();
}

class C : I
{
    public int P { get; set; }
    void I.M() { Console.WriteLine("M!"); }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以使用这样的类型:

C obj = new C();
obj.P = 3;
((I)obj).M();
Run Code Online (Sandbox Code Playgroud)

但这不会编译:

obj.M();
Run Code Online (Sandbox Code Playgroud)

正如JeffN825所指出的,实现接口成员明确性的一个原因是它们不受类型的支持.例如,Add抛出异常(相关讨论).实现成员显式的另一个原因是它复制了另一个具有不同名称的公共成员.这Count就是明确实施的原因; 相应的公共成员Length. 最后,一些成员是隐式实现的,即索引器.这两行都有效(假设arr是一个数组int):

arr[0] = 8;
((IList<int>)arr)[0] = 8;
Run Code Online (Sandbox Code Playgroud)


Jef*_*eff 12

因为Array不支持IList的所有功能(添加/删除/等),所以IList.Count(以及其他几种方法)都是私有地(显式地)实现的.你可以在反汇编中看到这个:

int ICollection.Count
Run Code Online (Sandbox Code Playgroud)

如果你真的想使用Count,你可以做到

((IList)myArray).Count
Run Code Online (Sandbox Code Playgroud)