我想知道是否有时候在foreach循环中使用IEnumerator来迭代集合是否有利?例如,有没有时间使用以下代码示例中的任何一个而不是另一个?
IEnumeratorclassesEnum = myClasses.GetEnumerator(); while(classesEnum.MoveNext()) Console.WriteLine(classesEnum.Current);
代替
foreach (var class in myClasses) Console.WriteLine(class);
Marc Gravell.. 31
首先,请注意您的示例(在foreach
和之间GetEnumerator
)的一个重大区别是,如果迭代器是,则foreach
保证调用Dispose()
迭代器IDisposable
.这对于许多迭代器(例如,可能正在消耗外部数据馈送)很重要.
实际上,有些情况foreach
并不像我们想的那样有用.
首先,这里讨论了"第一项"案例(foreach /检测第一次迭代).
还有一点; 如果你尝试编写丢失的Zip
方法将两个可枚举的序列拼接在一起(或SequenceEqual
方法),你会发现你可以'使用foreach
两个序列,因为那将执行交叉连接.您需要直接为其中一个使用迭代器:
static IEnumerableZip (this IEnumerable left, IEnumerable right) { using (var iter = right.GetEnumerator()) { // consume everything in the first sequence foreach (var item in left) { yield return item; // and add an item from the second sequnce each time (if we can) if (iter.MoveNext()) { yield return iter.Current; } } // any remaining items in the second sequence while (iter.MoveNext()) { yield return iter.Current; } } } static bool SequenceEqual (this IEnumerable left, IEnumerable right) { var comparer = EqualityComparer .Default; using (var iter = right.GetEnumerator()) { foreach (var item in left) { if (!iter.MoveNext()) return false; // first is longer if (!comparer.Equals(item, iter.Current)) return false; // item different } if (iter.MoveNext()) return false; // second is longer } return true; // same length, all equal }
Jay Bazuzi.. 19
根据C#语言规范:
表格的foreach声明
foreach (V v in x) embedded-statement
然后扩展到:
{ E e = ((C)(x)).GetEnumerator(); try { V v; while (e.MoveNext()) { v = (V)(T)e.Current; embedded-statement } } finally { ... // Dispose e } }
你的两个例子的本质是相同的,但有一些重要的区别,最值得注意的是try
/ finally
.
首先,请注意您的示例(在foreach
和之间GetEnumerator
)的一个重大区别是,如果迭代器是,则foreach
保证调用Dispose()
迭代器IDisposable
.这对于许多迭代器(例如,可能正在消耗外部数据馈送)很重要.
实际上,有些情况foreach
并不像我们想的那样有用.
首先,这里讨论了"第一项"案例(foreach /检测第一次迭代).
还有一点; 如果你尝试编写丢失的Zip
方法将两个可枚举的序列拼接在一起(或SequenceEqual
方法),你会发现你可以'使用foreach
两个序列,因为那将执行交叉连接.您需要直接为其中一个使用迭代器:
static IEnumerableZip (this IEnumerable left, IEnumerable right) { using (var iter = right.GetEnumerator()) { // consume everything in the first sequence foreach (var item in left) { yield return item; // and add an item from the second sequnce each time (if we can) if (iter.MoveNext()) { yield return iter.Current; } } // any remaining items in the second sequence while (iter.MoveNext()) { yield return iter.Current; } } } static bool SequenceEqual (this IEnumerable left, IEnumerable right) { var comparer = EqualityComparer .Default; using (var iter = right.GetEnumerator()) { foreach (var item in left) { if (!iter.MoveNext()) return false; // first is longer if (!comparer.Equals(item, iter.Current)) return false; // item different } if (iter.MoveNext()) return false; // second is longer } return true; // same length, all equal }
根据C#语言规范:
表格的foreach声明
foreach (V v in x) embedded-statement
然后扩展到:
{ E e = ((C)(x)).GetEnumerator(); try { V v; while (e.MoveNext()) { v = (V)(T)e.Current; embedded-statement } } finally { ... // Dispose e } }
你的两个例子的本质是相同的,但有一些重要的区别,最值得注意的是try
/ finally
.
在C#中,foreach
与IEnumerator
上面发布的代码完全相同.foreach
提供该构造以使程序员更容易.我相信在两种情况下产生的IL都是相同/相似的.