了解迭代器块和Dispose方法 [英] Understanding Iterator Blocks and Dispose Method

查看:178
本文介绍了了解迭代器块和Dispose方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看全碟的哥本哈根C#谈话视频和我结束了这段代码。

问:

什么是成品代码打印完毕后发生。我的意思是,为什么 iterator.MoveNext() 失败?



 代码:

类IteratorBlocks
{
公共静态的IEnumerable<串GT; GetStringsForever()
{
串电流=;
字符nextChar ='A';

{
,而(真)
{
电流+ = nextChar;
nextChar ++;

如果(nextChar>'Z')
{
nextChar ='A';
}

产量返回电流;
}
}
终于
{
Console.WriteLine(成品);
}
}
}

类节目
{

静态无效的主要(字串[] args)
{
IEnumerable的<串GT;字符串= IteratorBlocks.GetStringsForever();

&的IEnumerator LT;字符串>迭代= strings.GetEnumerator();

的for(int i = 0;我小于10;我++)
{
iterator.MoveNext();
Console.WriteLine(iterator.Current);
}

/ *
我不能够得到什么代码正在做超出这一行?
* /

iterator.Dispose();

的for(int i = 0;我小于10;我++)
{
iterator.MoveNext();
Console.WriteLine(iterator.Current);
}

}
}

输出:

A
AB
ABC
ABCD
ABCDE
ABCDEF
ABCDEFG
ABCDEFGH
ABCDEFGHI
ABCDEFGHIJ
成品
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ
ABCDEFGHIJ


解决方案

调用的MoveNext()只是要在返回其他没有做任何事情,因为你已经设置在迭代器。由C#编译器内置状态机将进入后状态,并呆在那里。看到C#3规范的详细信息部分10.14.4.2。



电流属性将继续返回最后价值它返回 - 在这种情况下的行为是在MSDN 明确定义。 (我敢发誓,那是为了抛出异常,但显然不是。)



这是否有意义? 的Dispose 不重置迭代器(和的 重置 方法本身没有被C#迭代器块支持)。如果你想再次重复,需要调用的GetEnumerator 试。



现在,我不记得确切我在哥本哈根谈话说,这样的道歉,如果任何这似乎违背什么录像显示:)


I am watching Jon Skeet's Copenhagen C# talk videos and I ended up with this code.
QUESTION:
What is happening after the code prints Finished. I mean why is iterator.MoveNext() failing?

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

解决方案

Calling MoveNext() is just going to be returning false without doing anything else, as you've disposed of the iterator. The state machine built by the C# compiler will go into the "after" state, and stay there. See section 10.14.4.2 of the C# 3 spec for details.

The Current property will continue to return the last value it returned - the behaviour in this situation is explicitly undefined in MSDN. (I could have sworn it was meant to throw an exception, but apparently not.)

Does that make sense? Dispose doesn't "reset" the iterator (and the Reset method itself isn't supported by C# iterator blocks). If you want to iterate again, you need to call GetEnumerator again.

Now, I can't remember exactly what I said in the Copenhagen talk, so apologies if any of this appears to go against what the video shows :)

这篇关于了解迭代器块和Dispose方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆