IEnumerable IEnumerator有和没有当前moveNext重置

时间:2014-07-15 15:17:00

标签: c# .net collections ienumerable ienumerator

我试图理解IEnumerable接口如何工作,但发现很难理解这个概念,因为一些例子使用IEnumerator,GetEnumerator,Current,moveNext,Reset和一些例子演示IEnumerable与IEnumerator没有Current,moveNext,重置与嵌套内部类。

我需要一个简单的例子来理解这个概念,以及什么时候使用IEnumerator与Current,moveNext,Reset以及何时不适用。

2 个答案:

答案 0 :(得分:3)

几乎从不适合使用Reset(),因为该方法显然不可靠:例如,迭代器块不支持它。因此,实施该计划几乎没有必要担心。

如果你的意思是在实现它:大多数时候,最合适的事情是使用迭代器块(又名yield return),因为这样做是手工操作很难,容易出错,通常没有什么用处。你需要有一些非常具体的东西,以保证手动实施一个普查员。

您看到的一些示例可能将迭代器块添加到语言之前的日期;在这种情况下,他们没有选择除了手工编写迭代器。

大多数时候:让编译器担心繁重的工作。 yield return是你的朋友。注意:List<T>之类的东西使用值类型的自定义迭代器等来最小化影响;请注意,当您foreach超过List<T>时,您实际上并未使用IEnumerable<T> - 您只是使用原始GetEnumerator()和关联的API。 foreach 可以使用 IEnumerable<T>,但不需要

答案 1 :(得分:0)

提供者========

这是一个我从枚举器中分离出类的例子。 MyEnumerableClass是Enumerable,所以如果有人需要枚举它,它可以检索类上的枚举器。

using System;
using System.Collections;


class MyEnumerableClass : IEnumerable
{
    public IEnumerator GetEnumerator()
    {
        return new MyEnumerableClassEnumerator();
    }
}

枚举器负责枚举类中的元素。 在这个例子中,我没有这个,我希望以这种方式更清楚。 在此示例中,类MyEnumerableClass和该类上的枚举器(MyEnumerableClassEnumerator)不相关。通常,枚举器枚举类中包含的内容,以便枚举器保持对类的引用。此外,如果类的状态发生了重大变化&#34;,则枚举器无法枚举它,因此它应该引发InvalidOperationException。通常在类中添加版本标识符(即int versionId)来实现此行为。枚举器被枚举后,它会保存versionId。如果在MoveNext调用中,枚举器看到versionId已更改,则会引发异常。 通过这种方式,您可以同时在同一个类上激活多个枚举器。 无论如何,这里是一个非常简单的枚举器示例

class MyEnumerableClassEnumerator : IEnumerator
{
    int myStatusVariable = 0;

    public object Current
    {
        get { return myStatusVariable; }
    }

    public bool MoveNext()
    {
        return ++myStatusVariable < 10;
    }

    public void Reset()
    {
        myStatusVariable = 0;
    }
}

消费者======== 现在的消费者。 您可以通过语言(生成接口调用)或自己生成调用两种方式使用anumerator

这里的示例基于上面的类

        MyEnumerableClass myEnumerableClass = new MyEnumerableClass();

        foreach (var item in myEnumerableClass)
        {
            Console.WriteLine(item);
        }


        IEnumerator enumerator = myEnumerableClass.GetEnumerator();
        while (enumerator.MoveNext())
        {
            Console.WriteLine(enumerator.Current);
        }