Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IEnumerable IEnumerator(带和不带当前移动下一次重置)_C#_.net_Collections_Ienumerable_Ienumerator - Fatal编程技术网

C# IEnumerable IEnumerator(带和不带当前移动下一次重置)

C# IEnumerable IEnumerator(带和不带当前移动下一次重置),c#,.net,collections,ienumerable,ienumerator,C#,.net,Collections,Ienumerable,Ienumerator,我试图理解IEnumerable接口是如何工作的,但发现很难理解这个概念,因为有些示例使用IEnumerator、GetEnumerator、Current、moveNext、Reset,有些示例演示了IEnumerable和IEnumerator,但没有Current、moveNext、Reset以及嵌套的内部类 我需要一个简单的例子来理解这个概念,以及何时适合将IEnumerator与Current、moveNext、Reset和when not一起使用。使用Reset()几乎从来都不合适,

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


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

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

如果您是指实现它:大多数情况下,最合适的做法是使用迭代器块(aka
yield return
),因为手工操作很难,容易出错,而且通常没有什么用处。为了保证手工实现枚举器,您需要考虑一些非常具体的东西

您看到的一些示例可能是在迭代器块被添加到语言之前出现的;在这种情况下,除了手工编写迭代器,他们别无选择

大多数情况下:让编译器担心繁重的工作<代码>收益回报是你的朋友。注意:
List
使用自定义迭代器,该迭代器是值类型的,以尽量减少影响;请注意,当您在
列表上使用
foreach
时,您甚至没有实际使用
IEnumerable
——您只是在使用原始
GetEnumerator()
和相关的API
foreach
可以使用
IEnumerable
,但不需要它。

提供程序========

这里是一个我从枚举器中分离类的例子。 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;
    }
}

消费?还是实施?@MarcGravel。如果您能从这两个角度提供解释,我将不胜感激。Thanks@MarcGravell. 对于.NET4.5,我通常不需要实现IEnumerator,对吗?它实际上不是.NET运行时特性;它是一种编译器特性;IIRC、迭代器块从C#2.0开始就存在,而.NET 4.5的编译器版本要高得多,因此:yes@MarcGravell. 什么时候我们真的需要消费IEnumerable?
        MyEnumerableClass myEnumerableClass = new MyEnumerableClass();

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


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