vto*_*ola 2 c# ienumerable ienumerator
为什么a Enumerator不跟踪同一功能中的项目,如果MoveNext 操作发生在其他功能中则不然?
例:
public static void Test()
{
var array = new List<Int32>(new Int32[] { 1, 2, 3, 4, 5 });
var e = array.GetEnumerator();
e.MoveNext();
e.MoveNext();
Console.WriteLine(e.Current); // 2
Incremenet(e);
Console.WriteLine(e.Current); //2
}
static void Incremenet(IEnumerator<Int32> e)
{
Console.WriteLine("Inside " + e.Current); //2
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 3
e.MoveNext();
Console.WriteLine("Inside " + e.Current); //4
}
Run Code Online (Sandbox Code Playgroud)
我期望在最后一个CW中获得5分,但是我得到2分,就像它从未增加过一样.函数返回时为什么忘记函数MoveNext内部Increment?
干杯.
List<T>的枚举器类型List<T>.Enumerator不是a class,而是a struct.由于GetEnumerator暴露了返回类型List<T>.Enumerator,当你使用时var,e类型是List<T>.Enumerator,所以当你传递它时Incremenet,它会被自动装箱成一个IEnumerator<Int32>对象.这是你所看到的奇怪行为的原因.
如果键入e作为IEnumerator<Int32>,拳击,只要你得到的对象发生,所以这种奇怪的行为不会发生:它的工作原理,你是否在运行其他代码相同Test或Increment(我固定在该方法的拼写,顺便说一句,它不是"Incremenet").
public static void Test()
{
var array = new List<Int32> { 1, 2, 3, 4, 5 };
IEnumerator<Int32> e = array.GetEnumerator(); // boxed here
e.MoveNext();
e.MoveNext();
Console.WriteLine(e.Current); // 2
Increment(e);
Console.WriteLine(e.Current); // now it's 4
}
static void Increment(IEnumerator<Int32> e)
{
Console.WriteLine("Inside " + e.Current); // 2
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 3
e.MoveNext();
Console.WriteLine("Inside " + e.Current); // 4
}
Run Code Online (Sandbox Code Playgroud)
它是暴露的类型,而不是IEnumerator<T>出于性能原因.在这种情况下,它foreach 足够聪明,可以调用MoveNext并且Current不需要装箱或虚拟调度,并且可以毫无问题地处理值类型语义.它确实引起了混乱,正如你所看到的那样,当你不小心处理它的方式时,因为可变的structs是邪恶的.