C#中,何時用yield return

yield關鍵字用於遍歷循環中,yield return用於返回IEnumerable<T>,yield break用於終止循環遍歷。spa

 

有這樣的一個int類型的集合:調試

static List<int> GetInitialData()
        {
            return new List<int>(){1,2,3,4};
        }

須要打印出全部值大於2的元素。code

 

  不使用yield return的實現blog

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,4get

 

  使用yeild return實現編譯器

static IEnumerable<int> FilterWithYield()
        {
            foreach (int i in GetInitialData())
            {
                if (i > 2)
                {
                    yield return i;
                }
            }
            yield break;
            Console.WriteLine("這裏的代碼不執行");
        }

客戶端調用:string

static void Main(string[] args)
        {
            foreach (var item in FilterWithYield())
            {
                Console.WriteLine(item);
            }
            Console.ReadKey(); 
        }

輸出結果:3,4it

 

  總結編譯

經過單步調試發現:

雖然2種方法的輸出結果是同樣的,但運做過程迥然不一樣。第一種方法,是把結果集所有加載到內存中再遍歷;第二種方法,客戶端每調用一次,yield return就返回一個值給客戶端,是"按需供給"。


第一種方法,客戶端調用過程大體爲:

1

 

使用yield return,客戶端調用過程大體爲:

2

 

使用yield return爲何能保證每次循環遍歷的時候從前一次中止的地方開始執行呢?

--由於,編譯器會生成一個狀態機來維護迭代器的狀態。

 

簡單地說,當但願獲取一個IEnumerable<T>類型的集合,而不想把數據一次性加載到內存,就能夠考慮使用yield return實現"按需供給"。

相關文章
相關標籤/搜索