尽管事实是, method should never be used在List<T>中发现了方法实现的奇怪行为。
无论您如何检查.NET框架源代码(尝试使用引用源和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我错过了什么简单的解释吗?
发布于 2013-09-30 17:52:54
我错过了什么简单的解释吗?
是的:你在这里对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();
}这很棘手,因为它使用显式接口实现。
我还没有测试过,但我认为这对你有用。很明显这是个坏主意。
编辑:或者,只需将变量类型更改为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);
}https://stackoverflow.com/questions/19100592
复制相似问题