C# 理解迭代器块和Dispose方法

C# 理解迭代器块和Dispose方法,c#,iterator,C#,Iterator,我正在看Jon Skeet的视频,我最终得到了这个代码 问题: 代码打印完成后发生的事情。我是说为什么迭代器.MoveNext()失败了 CODE: class IteratorBlocks { public static IEnumerable<string> GetStringsForever() { string current = ""; char nextChar = 'a';

我正在看Jon Skeet的视频,我最终得到了这个代码
问题:
代码打印完成后发生的事情。我是说为什么迭代器.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
代码:
类迭代器锁
{
公共静态IEnumerable GetStringsForver()
{
字符串current=“”;
char nextChar='a';
尝试
{
while(true)
{
电流+=nextChar;
nextChar++;
如果(下一步>z')
{
nextChar='a';
}
产生回流电流;
}
}
最后
{
控制台。写入线(“完成”);
}
}
}
班级计划
{
静态void Main(字符串[]参数)
{
IEnumerable strings=IteratorBlocks.getStringsForver();
IEnumerator迭代器=strings.GetEnumerator();
对于(int i=0;i<10;i++)
{
iterator.MoveNext();
Console.WriteLine(迭代器.Current);
}
/* 
我无法获得代码在这一行之外所做的事情?
*/
迭代器.Dispose();
对于(int i=0;i<10;i++)
{
iterator.MoveNext();
Console.WriteLine(迭代器.Current);
}
}
}
输出:
A.
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
完成了
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
abcdefghij
调用
MoveNext()
只会返回
false
,而不做任何其他操作,因为您已经处理了迭代器。由C#编译器构建的状态机将进入“after”状态,并保持不变。详见C#3规范第10.14.4.2节

Current
属性将继续返回它返回的最后一个值-这种情况下的行为是。(我本可以发誓它是要抛出异常的,但显然不是。)

这有意义吗
Dispose
不会“重置”迭代器(并且C#迭代器块不支持该方法本身)。如果要再次迭代,需要再次调用
GetEnumerator


现在,我记不清我在哥本哈根会谈中到底说了什么,因此,如果其中任何一条与视频显示的内容不符,我深表歉意:)

当您使用.NET的迭代器模式和收益率返回时,您将得到一个为您构建的小型状态机。调用dispose将状态机移动到其最终状态。在最后一种状态下,迭代器将不再向前移动,但它将记住它的最后一种状态(当前)。如果您查看生成的IL(或者可能是通过反射镜,尚未尝试),它会变得非常清晰。

如果您继续处理已处理的对象,会发生奇怪的事情

@Jon别担心Jon你在谈话中没有说错:-)。实际上,我不小心复制粘贴了第二个for循环,然后遇到了麻烦。谢谢(+1A)。@Jon'Dispose不会“重置”迭代器,但在这种情况下它会做什么?@david:它会使迭代器停止-它会将迭代器置于“之后”状态,此时进一步调用MoveNext()只会返回false,而不做任何其他操作。这取决于对象。Dispose()可用于提供“重置”行为。在MemoryStream的情况下,您仍然可以在处理后使用ToArray获取数据,这可能很有用。这是一种偶然的语言功能吗?或者它将在未来的.net版本中继续工作?