C#中的yield return與Unity中的Coroutine(協程)(上),
C#中的yield return
C#語法中有個特別的關鍵字yield, 它是干什麼用的呢?
來看看專業的解釋:
yield 是在迭代器塊中用於向枚舉數對象提供值或發出迭代結束信號。它的形式為下列之一:
yield return <expression>;
yield break
看如下例子:

![]()
1 1 public class CustomCollection :IEnumerable {
2 2
3 3 public static void Main (string[] args)
4 4 {
5 5 CustomCollection cc = new CustomCollection ();
6 6
7 7 foreach (String word in cc) {
8 8 Console.WriteLine ("word:" +word);
9 9 }
10 10 }
11 11
12 12 public IEnumerator GetEnumerator(){
13 13
14 14 yield return "Hello";
15 15 yield return "Boys";
16 16 yield return "And";
17 17 yield return "Girls";
18 18 //return new HelloBoyGirls();
19 19
20 20 }
21 21 }
22 22
23 23 // public class HelloBoyGirls: IEnumerator {
24 24 // private int cusor = -1;
25 25 // private String[] words = {"Hello", "Boys", "And", "Girls"};
26 26 //
27 27 // public bool MoveNext ()
28 28 // {
29 29 // cusor++;
30 30 // return cusor < words.Length;
31 31 // }
32 32 //
33 33 // public void Reset ()
34 34 // {
35 35 // cusor = 0;
36 36 // }
37 37 //
38 38 // public object Current {
39 39 // get {
40 40 // return words [cusor];
41 41 // }
42 42 // }
43 43 // }
View Code
上面的例子是實現了一個自定義的迭代器;實現可迭代(可以用foreach)的數據集合,必須實現GetEmumerator()方法,返回實現了IEmumerator的對象實例。
完成這個, 有兩種方法,一種是用上面注釋掉的代碼,一種是用yield return. yield return 需要配合IEmumerator進行使用, 在外部foreach循環中,它會執行GetEmumerator()方法,遇到yield return, 做了如下兩件事情:
1.記錄下當前執行到的代碼位置
2. 將代碼控制權返回到外部, yield return 後面的值, 作為迭代的當前值。
當執行下一個循環, 從剛才記錄的代碼位置後面, 開始繼續執行代碼。
簡單地說, yield return 就是實現IEmumerator的超級簡化版, 是不是很簡單?
那麼問題又來了, yield return 是如何決定循環該結束,yield return 之後的代碼, 什麼時候執行呢?
把上面的例子改造一下, 不要用方便的foreach了, 用while 循環自己控制:

![]()
1 public class CustomCollection :IEnumerable {
2
3 public static void Main (string[] args)
4 {
5 CustomCollection cc = new CustomCollection ();
6
7 IEnumerator enumerator = cc.GetEnumerator ();
8 while (true) {
9 bool canMoveNext = enumerator.MoveNext ();
10 Console.WriteLine ("canMoveNext:" +canMoveNext);
11 if (!canMoveNext)
12 break;
13 Object obj = enumerator.Current;
14 Console.WriteLine ("current obj:" +obj);
15 }
16 // foreach (String word in cc) {
17 // Console.WriteLine ("word:" +word);
18 // }
19 Console.WriteLine ("Main End.");
20
21 }
22
23 public IEnumerator GetEnumerator(){
24
25 yield return "Hello";
26 yield return "Boys";
27 yield return "And";
28 yield return "Girls";
29
30 Console.WriteLine ("After all yield returns.");
31 //return new HelloBoyGirls();
32
33 }
34 }
View Code
運行代碼, 結果是:
canMoveNext:True
current obj:Hello
canMoveNext:True
current obj:Boys
canMoveNext:True
current obj:And
canMoveNext:True
current obj:Girls
After all yield returns.
canMoveNext:False
Main End.
說明, 在GetEmumerator()中, 只有yield return 語句, 外部調用MoveNext()都為true, current就是yield return後面的對象
除了yield return, 還有yield break; yield break 的作用是, 停止循環, MoveNext()為false, yield break 之後的語句, 不會被執行!
有興趣的童鞋, 可以自己寫個例子試試。