【发布时间】:2009-10-28 02:40:21
【问题描述】:
我一直在思考IEnumerator.Reset() 方法。我在 MSDN 文档中读到它仅用于 COM 互操作。作为一名 C++ 程序员,在我看来,支持Reset 的IEnumerator 就是我所说的forward iterator,而不支持Reset 的IEnumerator 实际上是input iterator。
所以我的问题之一是,这种理解是否正确?
我的问题的第二部分是,如果在输入迭代器和前向迭代器(或“枚举器”,如果您愿意的话)之间存在区别,在 C# 中会有什么好处吗?是否有助于消除程序员之间的一些困惑,就像在SO question about cloning iterators 中发现的那样?
编辑:澄清转发和输入迭代器。输入迭代器仅保证您只能枚举集合的成员(或来自生成器函数或输入流)一次。这正是 IEnumerator 在 C# 中的工作方式。是否可以枚举第二次,取决于是否支持Reset。前向迭代器没有这个限制。您可以根据需要多次枚举成员。
一些 C# 程序员不理解为什么 IEnumerator 不能可靠地用于多通道算法中。考虑以下情况:
void PrintContents(IEnumerator<int> xs)
{
while (iter.MoveNext())
Console.WriteLine(iter.Current);
iter.Reset();
while (iter.MoveNext())
Console.WriteLine(iter.Current);
}
如果我们在这种情况下调用PrintContents,没问题:
List<int> ys = new List<int>() { 1, 2, 3 }
PrintContents(ys.GetEnumerator());
但是请看以下内容:
IEnumerable<int> GenerateInts() {
System.Random rnd = new System.Random();
for (int i=0; i < 10; ++i)
yield return Rnd.Next();
}
PrintContents(GenerateInts());
如果IEnumerator 支持Reset,换句话说,支持多遍算法,那么每次迭代集合都会有所不同。这将是不可取的,因为这将是令人惊讶的行为。这个例子有点假,但它确实发生在现实世界中(例如从文件流中读取)。
【问题讨论】:
-
我想你的意思是
IEnumerator.Reset,而不是IEnumerable<T>.Reset,对吧? -
好的,谢谢!对此感到抱歉。
-
有趣的问题。但也许您应该稍微解释一下 C++ 语言,因为很多 C# 程序员都会看到这一点。输入迭代器和前向迭代器究竟是什么可能并不明显(特别是它们的单通道/多通道功能,这与这个问题真正相关)
标签: c# c++ ienumerable iterator