c# - List<T>.Enumerator IEnumerator.Reset()方法实现

标签 c# list ienumerator

尽管如此, 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);
}

很明显,它应该打印 True3两次。相反,结果是

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)实现。

我还没有测试过,但我认为这应该适合你。显然这样做是个坏主意...

编辑:或者,只需将您的变量类型更改为 IEnumeratorIEnumerator<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/

相关文章:

.net - IEnumerator:有一个空的 Dispose 方法是否正常?

c# - foreach 在 string[] 与 List<string> 的幕后

c# - 在 C# 中构造类/结构的最佳方法

list - Power BI - 用于引用值列表的 DAX 度量。计算每个经纪人的净营业额 - 更优雅的解决方案?

c# - 在 C# 中实现双向枚举器

python - 比较列表的顺序而不对现有数据进行排序

Python 列表推导式、子列表行和列

c# - 作为 .NET 进程运行时 Git diff 卡住

c# - 从字符串创建 IronPython(动态)对象

c# - 在电子邮件中添加了 Schema.org 标记,不会影响 Gmail 的收件箱,无论是在移动应用程序还是 Web 应用程序中