gpt4 book ai didi

c# - 迭代器 block 的编译器实现不正确?

转载 作者:太空狗 更新时间:2023-10-30 01:20:15 25 4
gpt4 key购买 nike

考虑 IEnumerator.Current 的文档:

Current also throws an exception if the last call to MoveNext returned false, which indicates the end of the collection

但是,迭代器 block 不会发生这种情况。例如:

void Main()
{
using (var enumerator = GetCounter().GetEnumerator())
{
for (int i = 0; i < 10; i++)
{
enumerator.MoveNext();
Console.WriteLine (enumerator.Current);
}
}
}

static IEnumerable<int> GetCounter()
{
for (int count = 0; count < 3; count++)
{
yield return count;
}
}

将简单地打印 8 次 2,不会抛出任何异常。看着 compiler transformation , Current 只是一个字段支持的属性,它总是返回字段的值,仅此而已。也许这是某种形式的优化?尽管如此,这看起来还是违反了契约(Contract)。

最佳答案

虽然您对 IEnumerator.Current 是正确的的文档, IEnumerator<T>.Current 's documentation声明该属性对于这种情况是未定义的。使用您的迭代器,它返回“2”。 List<T>的枚举器返回 default(T) , 和 T[]的抛出异常。这些都是有效的实现,因为它是未定义的。

Current is undefined under any of the following conditions:

  • The enumerator is positioned before the first element in the collection, immediately after the enumerator is created. MoveNext must be called to advance the enumerator to the first element of the collection before reading the value of Current.
  • The last call to MoveNext returned false, which indicates the end of the collection.
  • The enumerator is invalidated due to changes made in the collection, such as adding, modifying, or deleting elements.

值得注意的是,尽管它实现了接口(interface),但从 yield return 生成的代码没有正确实现 IEnumerator , 因为它继续返回 2在这种情况下:

IEnumerator enumerator = GetCounter().GetEnumerator();
for (int i = 0; i < 10; i++)
{
enumerator.MoveNext();
Console.WriteLine (enumerator.Current);
}

(为了比较,List<T> 做对了:如果你在结束后得到了IEnumerator.Current,它抛出异常,如果你在结束后调用IEnumerator<T>.Current,它返回default(T))

关于c# - 迭代器 block 的编译器实现不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19643518/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com