产量突破; - 疯狂的行为

时间:2009-09-24 13:24:44

标签: c# .net yield break

using System;
using System.Collections.Generic;
using System.Text;
using System.Collections;

namespace ConsoleApplication4
{
    class Program
    {
        static void Main (string[] args)
        {
            var test1 = Test1(1, 2);
            var test2 = Test2(3, 4);
        }

        static IEnumerable Test1(int v1, int v2)
        {
            yield break;
        }

        static IEnumerable Test2 (int v1, int v2)
        {
            return new String[] { };
        }
    }
}

“test1”似乎是一个IEnumerable,其中v1和v2(params)为字段,而“Test1”未被调用。

“Test2”的工作原理是“设计”:)

最近怎么回事?

2 个答案:

答案 0 :(得分:15)

Test1 调用,但除非您遍历结果,否则不会在yield break上找到断点。

基本上Test1被转换为一个为你实现IEnumerable的状态机......但你方法的所有主体都在那个状态机内,除非你使用状态机通过调用GetEnumerator()然后MoveNext()(或使用foreach循环),您将看不到您的身体执行。

有关详情,请参阅我的general iterator article和我的iterator implementation文章,以及Eric Lippert的两篇博文:Psychic Debugging part onePsychic Debugging part two

答案 1 :(得分:1)

由于您提到了Python,我将指出Python中的生成器与C#中的生成器非常相似。只有yield break单独将C#方法转换为生成器的微小差别,而raise StopIteration的Python等价物则不会。

>>> def f():
...     print "Beginning of generator"
...     if False: yield
...     print "End of generator"
... 
>>> it = f()
>>> it
<generator object at 0x94fae2c>
>>> it.next()
Beginning of generator
End of generator
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration