繁体   English   中英

为什么 IEnumerable<T> 从 IEnumerable 继承?

[英]Why does IEnumerable<T> inherit from IEnumerable?

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

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

而且, IList<T>不继承自 IList。

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

直接从马口(Hejlsberg):

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

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

<...剪...>

因此,为了回答您的问题, IEnumerable<T>继承自IEnumerable因为它可以! :-)

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

IEnumerable是一个“只读”接口——所以通用形式比非通用形式更具体并不重要。 实现两者都不会破坏任何东西。 IEnumerator.Current返回object ,而IEnumerator<T>.Current返回T - 没关系,因为您总是可以合法地转换为object ,尽管它可能意味着装箱。

将此与IList<T>IList - 您可以在IList上调用Add(object) ,而这对于任何特定的IList<T> (实际上不是IList<object> )很可能无效。

Brad Abram 在博客上写了 Anders对这个问题的回答。

这是为了向后兼容。 如果您调用一个需要普通 IEnumerable 的 .Net 1.1 函数,您可以传入您的通用 IEnumerable。

幸运的是,通用 IEnumerator 继承自旧式 IEnumerator

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

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

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

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

这是为了它可以与不支持泛型的类一起使用。 此外,.NET 泛型不允许您执行诸如将 IList<long> 转换为 IList<int> 之类的操作,因此当您需要固定基类或接口时,接口的非泛型版本可能非常有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM