这可能是一个老问题:为什么 IEnumerable< T> 继承自 IEnumerable

.NET就是这样做的,但它带来了一些麻烦。每次我编写一个类实现 IEumerable< T> 时,我必须编写两个 GetEnumerator()函数,一个用于 IEnumerable< T> 和另一个用于 IEnumerable

并且, IList< T> 不会从IList继承。

我不知道为什么 IEnumerable< T> 是以其他方式设计的。

有帮助吗?

解决方案

直接离开马口(Hejlsberg) :

  

理想情况下,所有通用集合接口(例如 ICollection< T> IList< T> )将从其非通用对应物继承,以便通用接口实例可以用于通用和非通用代码。例如,如果 IList< T> 可以传递给需要 IList 的代码,那将会很方便。

     

事实证明,唯一可能的通用接口是 IEnumerable&lt; T&gt; ,因为只有 IEnumerable&lt; T&gt; 是反变式的:In <代码> IEnumerable&lt; T&gt; ,类型参数T仅在“输出”中使用。位置(返回值)而不是“输入”职位(参数)。 ICollection&lt; T&gt; IList&lt; T&gt; 在输入和输出位置都使用T,因此这些接口是不变的。 (顺便说一句,如果T仅用于输入位置,那么它们将是反对变体,但这在这里并不重要。)

     

&LT; ...剪断...&GT;

所以,为了回答你的问题, IEnumerable&lt; T&gt; 继承自 IEnumerable ,因为它可以! : - )

其他提示

IEnumerable 的答案是:“因为它可以在不影响类型安全的情况下”。

IEnumerable 是“只读”的。接口 - 因此通用形式比非通用形式更具体并不重要。你不会通过实现两者来打破任何事情。 IEnumerator.Current 返回 object ,而 IEnumerator&lt; T&gt; .Current 返回 T - 这没关系,你可以总是合法地转换为 object ,虽然它可能意味着拳击。

将此与 IList&lt; T&gt; IList 进行比较 - 您可以在 IList Add(object) >,对于任何特定的 IList&lt; T&gt; (除了 IList&lt; object&gt; 之外的其他任何东西),这可能无效。

Brad Abram的以Anders的答案为博客这个问题。

这是为了向后兼容。如果你调用一个期望一个vanilla IEnumerable的.Net 1.1函数,你可以传入你的通用IEnumerable。

Luckilly,通用IEnumerator继承自旧式IEnumerator

我通常实现一个返回枚举器的私有方法,然后为旧式和新式GetEnumerator方法传递它。

    private IEnumerator<string> Enumerator() {
        // ...
    }

    public IEnumerator<string> GetEnumerator() {
        return Enumerator();
    }

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
        return Enumerator();
    }

这样就可以使用不支持泛型的类。此外,.NET泛型不允许您执行诸如强制转换IList&lt; long&gt;之类的操作。作为IList&lt; int&gt;,因此当您需要固定的基类或接口时,非通用版本的接口非常有用。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top