yield return可一次返回一个元素,并保留当前在代码中的位置,下次调用当前迭代器函数时,将从该位置从新执行。也就是说执行了yield return的时候,迭代器函数就返回了一个元素给foreach中in前面的一个元素,这时代码就执行了foreach方法中,当foreach本次执行完毕之后,程序的执行顺序又重新回到了刚才执行yield return的下一行代码(如果有的话)。

yield break可以终止迭代。发现一个有趣的现象。如果在迭代器函数中有try{}finally{}块,yield break之后不会再次执行try块中的代码,但是会执行finally块中的代码。如下代码和结果所示:

static void Main(string[] args) {
            foreach(int i in TestYield()) {
                Console.WriteLine("foreach获取值->" + i.ToString());
            }
            Console.ReadKey();
}    

static IEnumerable<int> TestYield() {
            try {
                Console.WriteLine("进入迭代器函数");
                for(int i = 0; i < 20; i++) {                    
                    if(i == 3) {
                        Console.WriteLine("执行yield break后,执行finally块中的代码,如果没有finally块,则当前迭代器函数TestYield会直接返回,不再执行本函数中的后续代码");
                        yield break;
                    }

                    Console.WriteLine("马上开始yield return返回一个元素值->{0}",i);    
                    yield return i;
                    Console.WriteLine("yield return返回一个元素到foreach中,foreach当次执行完后,代码执行顺序会马上回到这里");                   
                }

                Console.WriteLine("yield break 跳出来了!但不执行该条代码!");
            }           
            finally {
                Console.WriteLine("yield break 跳出来后!会执行finally中的代码!");
            }
        }  

上述代码执行后的结果:

 

迭代器函数的声明必须满足以下条件:

一、返回类型必须是IEnumerable、IEnumerable<T>、IEnumerator、IEnumerator<T>;

二、不能有任何ref或out参数。

 

异常处理:

一、不能将yield return语句置于try-catch块中。但是可以将yield return语句置于try-finally语句的try块中;

二、可以将yield break语句置于try或catch块中,但是不能将之置于finally块中;

三、如果foreach主体(在迭代器函数之外)引发异常,则将执行迭代器函数中的finally块。

 

 posted on 2016-11-18 15:15  F风  阅读(1011)  评论(0编辑  收藏  举报