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

Mor*_*eng 36 c# generics ienumerable

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

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

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

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

Mar*_*ett 50

直接从马的嘴里(Hejlsberg):

理想的情况是所有的泛型集合接口(例如ICollection<T>,IList<T>)将他们的非通用同行继承,使得通用接口实例可以与通用和非通用代码均可使用.例如,如果IList<T>可以将代码传递给期望的代码,那将会很方便IList.

事实证明,唯一可能的通用接口是IEnumerable<T>,因为只有IEnumerable<T>反变量:In IEnumerable<T>,类型参数T仅用于"输出"位置(返回值)而不用于"输入"位置(参数) ).ICollection<T>IList<T>在输入和输出位置使用T,因此这些接口是不变的.(顺便说一句,如果只在输入位置使用T,那么它们就会反对变形,但这并不重要.)

<...剪断...>

那么,回答你的问题,IEnumerable<T>继承IEnumerable因为它可以!:-)


Jon*_*eet 17

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

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

与此比较IList<T>,并IList-你可以调用Add(object)IList,而这很可能是针对任何特定无效IList<T>(比其他任何IList<object>时候).

布拉德·阿布拉姆(Brad Abram)的博客与安德斯(Anders)对这个问题的回答.