IEnumerator有和没有当前移动重置

本文关键字:移动 IEnumerator | 更新日期: 2023-09-27 18:12:56

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

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

IEnumerator有和没有当前移动重置

实际上从来都不适合使用Reset(),因为该方法显然不可靠:例如,迭代器块不支持它。因此,没有什么必要担心实现它。

如果你指的是实现它:大多数时候,最合适的方法是使用迭代器块(又名yield return),因为手工做这件事很难,容易出错,而且通常没有什么伟大的目的。您需要在头脑中有一些非常具体的东西来保证手动实现枚举器。

你看到的一些例子可能早于迭代器块被添加到语言;在这种情况下,除了,他们没有选择来手工编写迭代器。

大多数时候:让编译器去操心繁重的工作。yield return是你的朋友。注意:像List<T>这样的东西使用自定义迭代器,是值类型等,以尽量减少影响;请注意,当您在List<T>上使用foreach时,您甚至没有实际使用IEnumerable<T> -您只是使用原始GetEnumerator()和相关api。foreach 可以使用 IEnumerable<T>,但不需要

PROVIDER ========

下面是我将类从枚举数中分离出来的例子。MyEnumerableClass是可枚举的,所以如果有人需要枚举它,它可以在类上检索枚举器。

using System;
using System.Collections;

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

枚举器负责枚举类中的元素。在这个例子中,我没有这样做,我希望这样更清楚。在这个例子中,类MyEnumerableClass和该类上的枚举器(MyEnumerableClassEnumerator)是不相关的。通常枚举数枚举类中包含的内容,因此枚举数保留对类的引用。此外,如果类的状态发生了"显著"变化,枚举器就不能枚举它,因此它应该引发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;
    }
}

消费者= = = = = = = =现在是消费者。您可以通过两种方式使用枚举器,通过Language(生成接口调用)或自己生成调用

下面是基于上面的类的例子

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

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