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 之後的語句, 不會被執行!
有興趣的童鞋, 可以自己寫個例子試試。