在类中包含对列表的枚举器的引用似乎改变了它的行为。匿名类的示例:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new { E = list.GetEnumerator() };
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
我希望这可以打印&#34; 123&#34;,但它只打印零并且永不终止。具体类的相同示例:
public static void Main()
{
var list = new List<int>() { 1, 2, 3 };
var an = new Foo()
{
E = list.GetEnumerator()
};
while (an.E.MoveNext())
{
Debug.Write(an.E.Current);
}
}
public class Foo
{
public List<int>.Enumerator E { get; set; }
}
发生了什么?
答案 0 :(得分:6)
我对它进行了测试,对我而言,它也不适用于您的具体课程。
原因是List<T>.Enumerator
是可变 struct
而an.E
是属性。
编译器为每个自动属性生成一个支持字段,如下所示:
public class Foo
{
private List<int>.Enumerator _E;
public List<int>.Enumerator get_E() { return E; }
public void set_E(List<int>.Enumerator value) { E = value; }
}
struct
是一种值类型,因此每当您访问an.E
时,您都会获得该值的副本。
当您致电MoveNext()
或Current
时,您可以在该副本上调用它,并且此副本会发生变异。
下次访问an.E
以致电MoveNext()
或Current
时,您会获得尚未迭代的枚举器的新副本。
并且an.E.Current
是0
而不是1
因为 - 再次 - 你得到一个新的调查员MoveNext()
尚未被调用。
如果您想存储列表枚举器的参考,可以使用Foo
类型的属性声明您的班级IEnumerator<int>
:
public class Foo
{
public IEnumerator<int> E { get; set; }
}
如果您现在分配E = list.GetEnumerator();
,则枚举器会被装箱并存储引用而不是值。