IEnumerable和IEnumerable <T>之间的区别?
IEnumerable
和IEnumerable<T>
什么区别?
我见过很多实现这两个接口的框架类,所以我想知道通过实现这两个接口有什么好处?
请看看他们是如何定义的:
public interface IEnumerable { [DispId(-4)] IEnumerator GetEnumerator(); } public interface IEnumerable<T> : IEnumerable { IEnumerator<T> GetEnumerator(); }
正如我们所看到的, IEnumerable<T>
从IEnumerable
派生,这意味着无论IEnumerable
具有什么, IEnumerable<T>
inheritance,那么为什么我们要实现而不仅仅是IEnumerable<T>
呢? 正在实现IEnumerable<T>
不够?
同样,还有其他类似的配对:
-
IList
和IList<T>
-
ICollection
和ICollection<T>
我也想知道这些。
在.NET 1.0和1.1中基本上是非属性接口。 然后,当.NET 2.0出来,generics等价物出来了。 如果仿制药进入到.NET 1.0中,生活将会变得更简单:)
在实现“唯一”的IEnumerable<T>
而不是两个 – 你基本上必须实现两个,你也必须使用显式接口实现,既定义了一个无参数的GetEnumerator
方法。 由于IEnumerator<T>
扩展IEnumerator
,所以通常是这样的:
public IEnumerator<T> GetEnumerator() { // Return real iterator } // Explicit implementation of nongeneric interface IEnumerator IEnumerable.GetEnumerator() { // Delegate to the generic implementation return GetEnumerator(); }
另一方面,使用C#2中引入的迭代器块(带有yield return
等),你很less需要手工完成这些事情,幸运的是。 您可能需要编写类似上面的内容,然后在GetEnumerator
方法中使用yield return
。
请注意, IList<T>
不会扩展IList
,并且ICollection<T>
不会扩展ICollection
。 这是因为这样做不是types安全的,而任何generics迭代器都可以被视为非generics迭代器,因为任何值(可能是装箱)转换为object
, IList
和ICollection
允许将值添加到集合中; 将一个string添加(比如说)给IList<int>
是没有意义的。
编辑:我们需要IEnumerable<T>
的原因是,我们可以以types安全的方式迭代,并传播信息。 如果我向您返回一个IEnumerable<string>
,那么您知道可以安全地假设从它返回的所有内容都将是一个string引用或null。 使用IEnumerable
,我们必须有效地(通常隐含在foreach
语句中)从序列返回的每个元素进行投射,因为IEnumerator
的Current
属性只是typesobject
。 至于为什么我们仍然需要IEnumerable
– 因为旧的界面从来没有消失,基本上。 现有的代码太多了。
IEnumerable<T>
可能不会扩展IEnumerable
,但是任何想要使用IEnumerable<T>
都不能调用接受IEnumerable
的方法 – 并且有很多这样的方法。 NET 1.1和1.0。
一个返回一个Objecttypes的对象,另一个返回一个Ttypes的对象。
至于为什么你看到类定义了两个,虽然IEnumerable <T>实现了IEnumerable,但它不是必须的,但在自我logging中有时会列出子接口。 考虑
interface IA { } interface IB : IA { } class A : IB {} // legal, IB implements IA class B : IA, IB {} // also legal, possible more clear on intent
在遍历循环时,IEnumerator维护状态。 它记得游标的位置,IEnumerable没有。