我想知道是否有时候在foreach循环中使用IEnumerator来迭代集合是否有利?例如,是否有时间使用以下任一代码示例而不是另一代码?
IEnumerator<MyClass> classesEnum = myClasses.GetEnumerator();
while(classesEnum.MoveNext())
Console.WriteLine(classesEnum.Current);
而不是
foreach (var class in myClasses)
Console.WriteLine(class);
答案 0 :(得分:31)
首先,请注意您的示例(foreach
和GetEnumerator
之间)的一个重大区别是,如果迭代器为{foreach
,则保证在迭代器上调用Dispose()
{1}}。这对于许多迭代器(例如,可能正在消耗外部数据馈送)非常重要。
实际上,有些情况IDisposable
没有我们想要的那样有用。
首先,讨论了here (foreach / detecting first iteration)的“第一项”案例。
但更多;如果你尝试编写缺少的foreach
方法将两个可枚举序列拼接在一起(或Zip
方法),你会发现你可以'在两个序列上使用SequenceEqual
,因为那会执行一个交叉联接。您需要直接为其中一个使用迭代器:
foreach
答案 1 :(得分:19)
表格的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
。
答案 2 :(得分:12)
在C#中,foreach
与您在上面发布的IEnumerator
代码完全相同。提供foreach
构造以使程序员更容易。我相信在两种情况下产生的IL都是相同/相似的。
答案 3 :(得分:4)
我有时会在第一次迭代做一些不同的事情时使用它。
例如,如果要将成员打印到控制台并按行分隔结果,可以编写。
using (IEnumerator<MyClass> classesEnum = myClasses.GetEnumerator()) {
if (classEnum.MoveNext())
Console.WriteLine(classesEnum.Current);
while (classesEnum.MoveNext()) {
Console.WriteLine("-----------------");
Console.WriteLine(classesEnum.Current);
}
}
然后结果是
myClass 1
-----------------
myClass 2
-----------------
myClass 3
另一种情况是我在一起迭代2个枚举器。
using (IEnumerator<MyClass> classesEnum = myClasses.GetEnumerator()) {
using (IEnumerator<MyClass> classesEnum2 = myClasses2.GetEnumerator()) {
while (classesEnum.MoveNext() && classEnum2.MoveNext())
Console.WriteLine("{0}, {1}", classesEnum.Current, classesEnum2.Current);
}
}
结果
myClass 1, myClass A
myClass 2, myClass B
myClass 3, myClass C
使用枚举器可以让您在迭代时更灵活。但在大多数情况下,您可以使用foreach