C# IEnumerable IEnumerator(带和不带当前移动下一次重置)
我试图理解IEnumerable接口是如何工作的,但发现很难理解这个概念,因为有些示例使用IEnumerator、GetEnumerator、Current、moveNext、Reset,有些示例演示了IEnumerable和IEnumerator,但没有Current、moveNext、Reset以及嵌套的内部类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()几乎从来都不合适,
我需要一个简单的例子来理解这个概念,以及何时适合将IEnumerator与Current、moveNext、Reset和when not一起使用。使用
Reset()
几乎从来都不合适,因为该方法显然不可靠:例如,迭代器块不支持它。因此,担心实施它没有什么意义
如果您是指实现它:大多数情况下,最合适的做法是使用迭代器块(akayield return
),因为手工操作很难,容易出错,而且通常没有什么用处。为了保证手工实现枚举器,您需要考虑一些非常具体的东西
您看到的一些示例可能是在迭代器块被添加到语言之前出现的;在这种情况下,除了手工编写迭代器,他们别无选择
大多数情况下:让编译器担心繁重的工作<代码>收益回报是你的朋友。注意:List
使用自定义迭代器,该迭代器是值类型的,以尽量减少影响;请注意,当您在列表上使用foreach
时,您甚至没有实际使用IEnumerable
——您只是在使用原始GetEnumerator()
和相关的APIforeach
可以使用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);
}