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块。