我什么时候应该使用IEnumerator在c#中进行循环?

时间:2009-01-19 03:19:01

标签: c# iterator ienumerable loops

我想知道是否有时候在foreach循环中使用IEnumerator来迭代集合是否有利?例如,是否有时间使用以下任一代码示例而不是另一代码?

IEnumerator<MyClass> classesEnum = myClasses.GetEnumerator();
while(classesEnum.MoveNext())
    Console.WriteLine(classesEnum.Current);

而不是

foreach (var class in myClasses)
    Console.WriteLine(class);

4 个答案:

答案 0 :(得分:31)

首先,请注意您的示例(foreachGetEnumerator之间)的一个重大区别是,如果迭代器为{foreach,则保证在迭代器上调用Dispose() {1}}。这对于许多迭代器(例如,可能正在消耗外部数据馈送)非常重要。

实际上,有些情况IDisposable没有我们想要的那样有用。

首先,讨论了here (foreach / detecting first iteration)的“第一项”案例。

但更多;如果你尝试编写缺少的foreach方法将两个可枚举序列拼接在一起(或Zip方法),你会发现你可以'在两个序列上使用SequenceEqual,因为那会执行一个交叉联接。您需要直接为其中一个使用迭代器:

foreach

答案 1 :(得分:19)

根据C# language spec

  

表格的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