很长一段时间我对以下内容感到好奇:
int[] array = new int[1];
int iArrayLength = array.Length; //1
由于数组实现IList接口,因此允许以下内容:
int iArrayCount = ((IList<int>)array).Count; //still 1
BUT:
int iArrayCount = array.Count; //Compile error. WHY?
int iArrayLength = array.Length; //This is what we learned at school!
问题:
数组如何实现IList<T>
(尤其是来自int Count { get; }
的{{1}}属性)而不允许它在基类上使用?
答案 0 :(得分:31)
这称为显式接口成员实现。接口成员不作为该类型的公共成员公开,但可以通过转换对接口类型的引用来实现。
这可以在C#中完成,如下所示:
interface I
{
void M();
}
class C : I
{
public int P { get; set; }
void I.M() { Console.WriteLine("M!"); }
}
然后你可以使用这样的类型:
C obj = new C();
obj.P = 3;
((I)obj).M();
但这不会编译:
obj.M();
正如JeffN825所指出的,实现接口成员明确性的一个原因是它们不受类型支持。例如,Add
会抛出异常(relevant discussion)。实现成员显式的另一个原因是它复制了另一个具有不同名称的公共成员。这是Count
明确实施的原因;相应的公共成员是Length.
最后,一些成员是隐式实现的,即索引器。这两行都有效(假设arr
是一个int
)数组:
arr[0] = 8;
((IList<int>)arr)[0] = 8;
答案 1 :(得分:12)
因为Array不支持IList的所有功能(添加/删除/等),所以IList.Count(和其他几种方法)都是私有地(显式地)实现的。你可以在反汇编中看到这个:
int ICollection.Count
如果你真的想使用Count,你可以做
((IList)myArray).Count