数组如何实现 IList<T> 而无需在 C# 中实现属性“Count”? [复制]

Posted

技术标签:

【中文标题】数组如何实现 IList<T> 而无需在 C# 中实现属性“Count”? [复制]【英文标题】:How do Arrays implement IList<T> without implementing the property "Count" in C#? [duplicate] 【发布时间】:2012-09-09 18:59:51 【问题描述】:

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

int[] array = new int[1];
int iArrayLength = array.Length;    //1

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

int iArrayCount = ((IList<int>)array).Count;    //still 1

但是:

int iArrayCount = array.Count;  //Compile error. WHY?
int iArrayLength = array.Length;    //This is what we learned at school!

问题: 数组如何实现IList&lt;T&gt;(尤其是来自IList&lt;T&gt;int Count get; 属性)而不允许在基类上使用?

【问题讨论】:

您可以自己模拟这种情况,方法是在您自己继承的类中隐藏基类的“Count”属性,并将其设为私有。 VB.NET 对此有一个明确的关键字“阴影”,但不确定 C#。 你的标题有误。数组实际上从ICollection实现Countint ICollection.Count get return this.Length; @TimSchmelter 但IList&lt;T&gt; 继承自ICollection&lt;T&gt;ICollection&lt;T&gt; 也有一个Count 属性,所以所有实现IList&lt;T&gt; 的类型也必须实现ICollection&lt;T&gt;.Count。确实,IList&lt;T&gt; 中没有定义该属性,但这个问题是合理的。 @phoog:除了它不是IList 的属性之外,它在数组中实现的,这就是我说标题是的主要原因错误的(“..没有实现..”)。 @TimSchmelter 啊哈,我明白了,我误解了你的意思。但是如果你从不了解显式接口实现的角度来阅读标题,那么这个问题就很有意义了。 (顺便说一句,“错误的”,而不是“错误的”)。 【参考方案1】:

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

这可以像这样在 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. 最后,一些成员是隐式实现的,即索引器。这两行都有效(假设arrint 的数组):

arr[0] = 8;
((IList<int>)arr)[0] = 8;

【讨论】:

“显式接口成员定义” google 的好关键字!我不知道,谢谢!有趣的是没有任何访问修饰符。所以你可以在公共类上使用你的内部接口,而不必将所有方法/属性都实现为公共的,很好! @Gerrit;实际上,这是不正确的。它应该是“显式接口成员实现”。我已经更正了。 @Gerrit Eric Lippert 有一个关于在公共类型上使用内部接口的有趣讨论:blogs.msdn.com/b/ericlippert/archive/2011/12/08/… @Gerrit Jon Skeet 在这里给出的非常彻底的答案比我的详细得多:***.com/a/11163336/385844 @phoog 有趣的链接。阅读乔恩与汉斯的辩论令人着迷:)【参考方案2】:

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

int ICollection.Count

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

((IList)myArray).Count

【讨论】:

以上是关于数组如何实现 IList<T> 而无需在 C# 中实现属性“Count”? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中返回 IList<T> vs Array?

IList<T> 和 IReadOnlyList<T>

如何转换通用IList IList?

哪个标准范围适用于C#8中的数组和字符串?

如何序列化 IList<T>?

如何对 IList<T> 执行二进制搜索?