程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 對[foreach]的淺究到發現[yield]

對[foreach]的淺究到發現[yield]

編輯:C#入門知識

  閒來無事,翻了翻以前的代碼,做點總結,菜鳥從這裡起航,呵呵。

一、List的foreach遍歷

  先上代碼段[1]:

 1  class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             List<string> dayList = new List<string> { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
 6             foreach (var day in dayList)
 7             {
 8                 Console.WriteLine(day);
 9             }
10             Console.ReadKey();
11         }
12     }

  這是我們經常用的,簡單明了,這裡就不贅述了。

二、對List的淺究

  接著我就產生了疑問,List具有怎樣的特性才使得foreach可以對它進行遍歷呢?這個遍歷是如何實現的?

  下面就來淺究,再上代碼段[2]:

 1     public class DaysList<T> : System.Collections.IEnumerable
 2     {
 3         T[] daysArry;
 4         public DaysList(T[] days)
 5         {
 6             daysArry = days;
 7         }
 8         public System.Collections.IEnumerator GetEnumerator()
 9         {
10             for (int i = 0; i < daysArry.Length; i++)
11             {
12                 yield return daysArry[i];
13             }
14         }
15     }
16 
17     class Program
18     {
19         static void Main(string[] args)
20         {
21             string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
22             var daysList = new DaysList<string>(days);
23 
24             foreach (string day in daysList)
25             {
26                 System.Console.WriteLine(day);
27             }
28             Console.ReadKey();
29         }
30     }

  通過查閱我們發現LIst是通過實現System.Collections.IEnumerable接口來達到可以被遍歷的能力,而實現System.Collections.IEnumerable接口必須實現它裡面的GetEnumerator()方法,用來返回一個循環訪問集合的枚舉器,代碼段[2]中就有我對GetEnumerator()方法的實現,其中有個關鍵字[yield]不知大家注意到沒。

  我的理解是:與其說是foreach遍歷List,不如說是foreach遍歷的是List中的GetEnumerator()方法返回的枚舉器,注意這個枚舉器實現了IEnumerator 接口,(插句話,IEnumerable接口標識某個類具備被遍歷的能力,而IEnumerator 接口則使某個類真正具備這個能力!)。而當foreach對List進行循環遍歷時,每個循環就是通過[yield]來分隔的。

三、對foreach的淺究

  通過標題二,我們大概對List進行了了解,但不清楚,下面看看foreach。

  依舊代碼段[3]:

 1     //注意:其中類DaysList<T>的實現同代碼段[2]一樣
 2     //這裡只展示foreach的實現。    
 3     class Program
 4     {
 5         static void Main(string[] args)
 6         {
 7             string[] days = { "Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat" };
 8             var daysList = new DaysList<string>(days);
 9 
10             System.Collections.IEnumerator enumertor = daysList.GetEnumerator();
11             while (enumertor.MoveNext())
12             {
13                 System.Console.WriteLine(enumertor.Current);
14             }
15             Console.ReadLine();
16         }
17      }

  就像上面說的,foreach其實遍歷的是List中的GetEnumerator()方法返回的枚舉器enumertor,而這個枚舉器所實現的接口IEnumerator中定義了只讀的Current屬性(用來獲取枚舉器當前的所指的集合中的元素)、MoveNext方法(將枚舉器推進到集合中的下一個元素,返回值代表是否到了集合末尾)、Reset方法(使枚舉器指到集合第一個元素之前,也就是重置枚舉器),明白了這些,我們就可以像代碼段[3]中一樣通過[while]語法來實現跟foreach一樣的功能了,而上文中的[yield]關鍵字淺顯的理解就是用來劃分要遍歷的集合中的每個元素的。

  最後,本來還想分析分析這個實現了IEnumerator接口的枚舉器是怎麼生成的,想象一下它的內部實現,應該很有意思!

  就這樣吧,下班了,大家共勉!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved