【问题标题】:Understanding Iterator Blocks and Dispose Method了解迭代器块和 Dispose 方法
【发布时间】:2010-12-24 18:20:36
【问题描述】:

我正在观看 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

【问题讨论】:

    标签: c# iterator


    【解决方案1】:

    如果您继续使用已处置的对象,就会发生奇怪的事情!

    【讨论】:

    • 这取决于对象。 Dispose() 可以 用于提供“重置”行为。在 MemoryStream 的情况下,您仍然可以在处理后使用 ToArray 获取数据,这可能很有用。
    • 这是一个偶然的语言功能吗?或者它是否会在 .net 的未来版本中继续发挥作用?
    【解决方案2】:

    调用MoveNext() 只会返回false 而不做任何其他事情,因为您已经处理了迭代器。 C# 编译器构建的状态机将进入“之后”状态,并停留在那里。有关详细信息,请参阅 C# 3 规范的第 10.14.4.2 节。

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

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

    现在,我不记得我在哥本哈根演讲中所说的确切内容,所以如果其中任何内容与视频显示的内容相悖,我深表歉意:)

    【讨论】:

    • @Jon 不要担心 Jon,你在谈话中没有说错 :-)。实际上,我不小心复制粘贴了第二个 for 循环,然后遇到了麻烦。谢谢 (+1A)。
    • @Jon 'Dispose 不会“重置”迭代器',但在这种情况下它会做什么?
    • @david:它只是让它停止 - 它把它置于“之后”状态,此时对 MoveNext() 的进一步调用只会返回 false 而不做任何其他事情。
    【解决方案3】:

    当您使用带有 yield return 的 .NET 迭代器模式时,您会得到一个为您构建的小型状态机。调用 dispose 将该状态机移至其最终状态。在那个最终状态下,迭代器将不再向前移动,但它会记住它的最后一个状态(当前)。如果您查看生成的 IL(或者可能通过 Reflector,尚未尝试过),就会非常清楚。

    【讨论】:

      猜你喜欢
      • 2021-10-13
      • 2021-01-29
      • 2016-04-18
      • 2011-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-22
      • 1970-01-01
      相关资源
      最近更新 更多