IEnumerable,IEnumerator vs foreach,何时使用什么

我正在通过IEnumerable和IEnumerator,但是没有明确地得到一点……如果我们有foreach,那么为什么我们需要这两个接口呢? 是否有任何我们必须使用接口的情况。如果是,那么有人可以用一个例子来解释。 欢迎任何建议和评论。 谢谢。

foreach在很多情况下使用接口。 如果要实现 foreach可以使用的序列,则需要接口。 (迭代器块通常会使这个实现任务变得非常简单。)

但是, 偶尔使用迭代器会很有用。 一个很好的例子是当试图“配对”两个不同的序列时。 例如,假设您收到两个序列 – 一个名称,一个年龄,并且您想要将两者打印在一起。 你可以写:

 static void PrintNamesAndAges(IEnumerable names, IEnumerable ages) { using (IEnumerator ageIterator = ages.GetEnumerator()) { foreach (string name in names) { if (!ageIterator.MoveNext()) { throw new ArgumentException("Not enough ages"); } Console.WriteLine("{0} is {1} years old", name, ageIterator.Current); } if (ageIterator.MoveNext()) { throw new ArgumentException("Not enough names"); } } } 

同样地,如果你想以不同的方式处理(比方说)第一个项目,那么使用迭代器会很有用:

 public T Max(IEnumerable items) { Comparer comparer = Comparer.Default; using (IEnumerator iterator = items.GetEnumerator()) { if (!iterator.MoveNext()) { throw new InvalidOperationException("No elements"); } T currentMax = iterator.Current; // Now we've got an initial value, loop over the rest while (iterator.MoveNext()) { T candidate = iterator.Current; if (comparer.Compare(candidate, currentMax) > 0) { currentMax = candidate; } } return currentMax; } } 

现在,如果您对IEnumeratorIEnumerable之间的区别感兴趣,您可能需要在数据库术语中考虑它:将IEnumerable视为表,将IEnumerator视为游标。 您可以要求一个表为您提供一个新游标,并且您可以同时在同一个表上使用多个游标。

真正理解这种差异可能需要一段时间,但只记得列表(或数组,或其他)没有任何“你在列表中的位置”的概念,而是在列表/数组上的迭代器/无论如何有一点状态是有帮助的。

乔恩说的话。

  • IEnumerableIEnumerable :通过实现这个对象声明它可以为您提供一个迭代器,您可以使用它来遍历序列/集合/集
  • IEnumeratorIEnumerator :如果调用前一个接口中定义的GetEnumerator方法,则会获得一个迭代器对象作为IEnumerator引用。 这使您可以调用MoveNext()并获取Current对象。
  • foreach :在某种意义上来说是一个C#构造/外观,因为你不需要知道它是如何工作的。 它在内部获取迭代器并调用正确的方法让您专注于您想要对每个项目执行的操作(foreach块的内容)。 大多数情况下,除非您实现自己的类型或自定义迭代,否则您只需要foreach,在这种情况下,您需要了解前2个接口。

请记住,您不必实现IEnumerator及其变量以使用foreach – IIRC,它只需要一个GetEnumerator()方法,该方法返回一个对象,该对象具有返回bool的MoveNext()方法,以及返回的Current属性一个东西。 您不需要使用IEnumerator和IEnumerable,尽管这样做通常是一个非常好的主意。 有关更多信息,请参见此处