[英]Why does IEnumerable<T> inherit from IEnumerable?
This might be a old question: Why does IEnumerable<T>
inherit from IEnumerable
?这可能是一个老问题:为什么
IEnumerable<T>
继承自IEnumerable
?
This is how .NET do, but it brings a little trouble.这就是 .NET 的做法,但它带来了一些麻烦。 Every time I write a class implements
IEumerable<T>
, I have to write two GetEnumerator()
functions, one for IEnumerable<T>
and the other for IEnumerable
.每次我写一个类实现
IEumerable<T>
,我必须写两个GetEnumerator()
函数,一个用于IEnumerable<T>
,另一个用于IEnumerable
。
And, IList<T>
doesn't inherit from IList.而且,
IList<T>
不继承自 IList。
I don't know why IEnumerable<T>
is designed in other way.我不知道为什么
IEnumerable<T>
是以其他方式设计的。
Straight from the horse's mouth (Hejlsberg): 直接从马口(Hejlsberg):
Ideally all of the generic collection interfaces (eg
ICollection<T>
,IList<T>
) would inherit from their non-generic counterparts such that generic interface instances could be used both with generic and non-generic code.理想情况下,所有泛型集合接口(例如
ICollection<T>
、IList<T>
)都将从其非泛型对应物继承,以便泛型接口实例可以与泛型和非泛型代码一起使用。 For example, it would be convenient if anIList<T>
could be passed to code that expects anIList
.例如,如果可以将
IList<T>
传递给需要IList
代码,那将会很方便。
As it turns out, the only generic interface for which this is possible is
IEnumerable<T>
, because onlyIEnumerable<T>
is contra-variant: InIEnumerable<T>
, the type parameter T is used only in "output" positions (return values) and not in "input" positions (parameters).事实证明,唯一可能的通用接口是
IEnumerable<T>
,因为只有IEnumerable<T>
是逆变的:在IEnumerable<T>
,类型参数 T 仅用于“输出”位置(返回值)而不是“输入”位置(参数)。ICollection<T>
andIList<T>
use T in both input and output positions, and those interfaces are therefore invariant.ICollection<T>
和IList<T>
在输入和输出位置都使用 T,因此这些接口是不变的。 (As an aside, they would have been contra-variant if T was used only in input positions, but that doesn't really matter here.)(顺便说一句,如果 T 仅用于输入位置,它们将是逆变的,但这在这里并不重要。)
<...snip...>
<...剪...>
So, to answer your question, IEnumerable<T>
inherits from IEnumerable
because it can!因此,为了回答您的问题,
IEnumerable<T>
继承自IEnumerable
因为它可以! :-) :-)
The answer for IEnumerable
is: "because it can without affecting type safety". IEnumerable
的答案是:“因为它可以不影响类型安全”。
IEnumerable
is a "readonly" interface - so it doesn't matter that the generic form is more specific than the nongeneric form. IEnumerable
是一个“只读”接口——所以通用形式比非通用形式更具体并不重要。 You don't break anything by implementing both.实现两者都不会破坏任何东西。
IEnumerator.Current
returns object
, whereas IEnumerator<T>.Current
returns T
- that's okay, as you can always legitimately convert to object
, although it may mean boxing. IEnumerator.Current
返回object
,而IEnumerator<T>.Current
返回T
- 没关系,因为您总是可以合法地转换为object
,尽管它可能意味着装箱。
Compare this with IList<T>
and IList
- you can call Add(object)
on an IList
, whereas that may well be invalid for any particular IList<T>
(anything other than IList<object>
in fact).将此与
IList<T>
和IList
- 您可以在IList
上调用Add(object)
,而这对于任何特定的IList<T>
(实际上不是IList<object>
)很可能无效。
Brad Abram's blogged with Anders' answer about this very question. Brad Abram 在博客上写了 Anders对这个问题的回答。
It's for backward compatibility.这是为了向后兼容。 If you call a .Net 1.1 function that expects a vanilla IEnumerable you can pass in your generic IEnumerable.
如果您调用一个需要普通 IEnumerable 的 .Net 1.1 函数,您可以传入您的通用 IEnumerable。
Luckilly the generic IEnumerator inherits from the old-style IEnumerator幸运的是,通用 IEnumerator 继承自旧式 IEnumerator
I usually implement a private method that returns an enumerator and then pass it for both the old and new style GetEnumerator method.我通常实现一个私有方法,它返回一个枚举器,然后将它传递给新旧样式的 GetEnumerator 方法。
private IEnumerator<string> Enumerator() {
// ...
}
public IEnumerator<string> GetEnumerator() {
return Enumerator();
}
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return Enumerator();
}
This is so that it will work with classes that do not support generics.这是为了它可以与不支持泛型的类一起使用。 Additionally, .NET generics don't let you do things like cast IList<long> as IList<int>, so non generic versions of interfaces can be quite useful when you need a fixed base class or interface.
此外,.NET 泛型不允许您执行诸如将 IList<long> 转换为 IList<int> 之类的操作,因此当您需要固定基类或接口时,接口的非泛型版本可能非常有用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.