IEnumerator有和没有当前移动重置
本文关键字:移动 IEnumerator | 更新日期: 2023-09-27 18:12:56
我试图理解IEnumerable接口是如何工作的,但发现很难理解这个概念,因为一些例子使用IEnumerator, GetEnumerator, Current,moveNext, Reset和一些例子演示IEnumerable与IEnumerator没有Current,moveNext, Reset与嵌套的内部类。
我需要一个简单的例子来理解这个概念,以及何时适合使用IEnumerator与Current, moveNext,Reset,何时不适合。
实际上从来都不适合使用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);
}