標籤:style blog http color 使用 strong
yield關鍵字用於遍曆迴圈中,yield return用於返回IEnumerable<T>,yield break用於終止迴圈遍曆。
有這樣的一個int類型的集合:
static List<int> GetInitialData() { return new List<int>(){1,2,3,4}; }
需要列印出所有值大於2的元素。
不使用yield return的實現
static IEnumerable<int> FilterWithoutYield() { List<int> result = new List<int>(); foreach (int i in GetInitialData()) { if (i > 2) { result.Add(i); } } return result; }
用戶端調用:
static void Main(string[] args) { foreach (var item in FilterWithoutYield()) { Console.WriteLine(item); } Console.ReadKey(); }
輸出結果:3,4
使用yeild return實現
static IEnumerable<int> FilterWithYield() { foreach (int i in GetInitialData()) { if (i > 2) { yield return i; } } yield break; Console.WriteLine("這裡的代碼不執行"); }
用戶端調用:
static void Main(string[] args) { foreach (var item in FilterWithYield()) { Console.WriteLine(item); } Console.ReadKey(); }
輸出結果:3,4
總結
通過單步調試發現:
雖然2種方法的輸出結果是一樣的,但運作過程迥然不同。第一種方法,是把結果集全部載入到記憶體中再遍曆;第二種方法,用戶端每調用一次,yield return就返回一個值給用戶端,是"按需供給"。
第一種方法,用戶端調用過程大致為:
使用yield return,用戶端調用過程大致為:
使用yield return為什麼能保證每次迴圈遍曆的時候從前一次停止的地方開始執行呢?
--因為,編譯器會產生一個狀態機器來維護迭代器的狀態。
簡單地說,當希望擷取一個IEnumerable<T>類型的集合,而不想把資料一次性載入到記憶體,就可以考慮使用yield return實現"按需供給"。