我正在观看Jon Skeet的Copenhagen C# talk视频,我最终得到了这段代码。
的问题:
代码打印完成后发生了什么。我的意思是为什么 iterator.MoveNext()
失败?
CODE:
class IteratorBlocks
{
public static IEnumerable<string> GetStringsForever()
{
string current = "";
char nextChar = 'a';
try
{
while (true)
{
current += nextChar;
nextChar++;
if (nextChar > 'z')
{
nextChar = 'a';
}
yield return current;
}
}
finally
{
Console.WriteLine("Finished");
}
}
}
class Program
{
static void Main(string[] args)
{
IEnumerable<string> strings = IteratorBlocks.GetStringsForever();
IEnumerator<string> iterator = strings.GetEnumerator();
for (int i = 0; i < 10; i++)
{
iterator.MoveNext();
Console.WriteLine(iterator.Current);
}
/*
I am not able to get what the code is doing beyond this line?
*/
iterator.Dispose();
for (int i = 0; i < 10; i++)
{
iterator.MoveNext();
Console.WriteLine(iterator.Current);
}
}
}
OUTPUT:
a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
Finished
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
答案 0 :(得分:7)
调用MoveNext()
只会返回false
而不做任何其他事情,因为你已经处理了迭代器。由C#编译器构建的状态机将进入“后”状态,并保持在那里。有关详细信息,请参阅C#3规范的第10.14.4.2节。
Current
属性将继续返回它返回的最后一个值 - 这种情况下的行为是explicitly undefined in MSDN。 (我本可以发誓这是为了抛出异常,但显然不是。)
这有意义吗? Dispose
不会“重置”迭代器(并且C#迭代器块不支持Reset
方法本身)。如果您想再次进行迭代,则需要再次调用GetEnumerator
。
现在,我不记得我在哥本哈根会谈中所说的具体内容,如果其中任何一个看起来与视频所显示的相反,请道歉:)
答案 1 :(得分:1)
当您使用.NET的迭代器模式和yield return时,您将获得一个为您构建的小型状态机。调用dispose会将状态机移动到最终状态。在最终状态中,迭代器将不再向前移动,但它将记住它的最后状态(当前)。如果你看一下生成的IL(或者可能通过Reflector,还没有尝试过),它就变得非常清楚了。
答案 2 :(得分:0)
如果你继续处理被处置的物体,就会发生奇怪的事情!