代码之家  ›  专栏  ›  技术社区  ›  Pratik Deoghare

了解迭代器块和Dispose方法

  •  2
  • Pratik Deoghare  · 技术社区  · 15 年前

    我在看乔恩·斯基特的 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
    
    3 回复  |  直到 15 年前
        1
  •  7
  •   Jon Skeet    15 年前

    打电话 MoveNext() 就要回来了 false 不用做任何其他事情,就像您处理迭代器一样。由C编译器构建的状态机将进入“后”状态,并保持在该状态。详见C 3规范第10.14.4.2节。

    这个 Current 属性将继续返回其返回的最后一个值-这种情况下的行为是 explicitly undefined in MSDN . (我本可以发誓,这是为了抛出一个例外,但显然不是。)

    这有道理吗? Dispose 不“重置”迭代器(和 Reset c迭代器块不支持方法本身)。如果要再次迭代,则需要调用 GetEnumerator 再一次。

    现在,我记不清我在哥本哈根会谈上说了些什么,所以如果有任何一个与视频显示的不符的话,我深表歉意。)

        2
  •  1
  •   Mike Two    15 年前

    当使用带有yield返回的.NET迭代器模式时,您将得到一个为您构建的小型状态机。调用Dispose会将该状态机移动到其最终状态。在该最终状态下,迭代器将不再向前移动,但它将记住它的最后一个状态(当前)。如果你观察生成的IL(或者通过反射镜,还没有尝试过),它会变得非常清晰。

        3
  •  0
  •   Mongus Pong    15 年前

    如果你继续处理一个处理过的物体,会发生奇怪的事情!