尽管如此, IEnumerator.Reset
method should never be used我在 List<T>
中发现了方法实现的奇怪行为.
无论您如何检查 .NET Framework 源代码(尝试使用引用源和 ILSpy),该方法的实现如下:
void System.Collections.IEnumerator.Reset() {
if (version != list._version) {
ThrowHelper.ThrowInvalidOperationException(ExceptionResource.InvalidOperation_EnumFailedVersion);
}
index = 0;
current = default(T);
}
但是,看起来这个方法根本就没有被调用过!考虑代码:
var list = new List<int>(1) { 3 };
using (var e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
((IEnumerator)e).Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
很明显,它应该打印 True
和 3
两次。相反,结果是
True
3
False
0
我缺少任何简单的解释吗?
最佳答案
Any simple explanation I'm missing?
是的:你正在装箱 List.Enumerator
这里:
((IEnumerator)e).Reset();
这会获取现有副本的副本并重置它 - 将原件留在一件中。
要重置实际 枚举器,您需要这样的东西:
var list = new List<int>(1) { 3 };
var e = list.GetEnumerator();
// Can't use "ref" with a using statement
try
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
Reset(ref e);
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
finally
{
e.Dispose();
}
static void Reset<T>(ref T enumerator) where T : IEnumerator
{
enumerator.Reset();
}
这很棘手,因为它使用显式接口(interface)实现。
我还没有测试过,但我认为这应该适合你。显然这样做是个坏主意...
编辑:或者,只需将您的变量类型更改为 IEnumerator
或 IEnumerator<int>
开始。然后它将被装箱一次,并且Reset
方法将改变装箱值:
var list = new List<int>(1) { 3 };
using (IEnumerator e = list.GetEnumerator())
{
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
e.Reset();
Console.WriteLine(e.MoveNext());
Console.WriteLine(e.Current);
}
关于c# - List<T>.Enumerator IEnumerator.Reset()方法实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19100592/