c# – List.Enumerator IEnumerator.Reset()方法实现

前端之家收集整理的这篇文章主要介绍了c# – List.Enumerator IEnumerator.Reset()方法实现前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
尽管如此,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();
}

这很棘手,因为它使用显式接口实现.

我没有测试过,但我认为这对你有用.显然这样做是个坏主意……

编辑:或者,只需将您的变量类型更改为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://www.f2er.com/csharp/97468.html

猜你在找的C#相关文章