您好,登錄后才能下訂單哦!
這篇文章主要介紹了C#中的yield關鍵字怎么用的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇C#中的yield關鍵字怎么用文章都會有所收獲,下面我們一起來看看吧。
以下代碼創建一個集合并遍歷集合。
class Program { static Random r = new Random(); static IEnumerable<int> GetList(int count) { List<int> list = new List<int>(); for (int i = 0; i < count; i++) { list.Add(r.Next(10)); } return list; } static void Main(string[] args) { foreach(int item in GetList(5)) Console.WriteLine(item); Console.ReadKey(); } }
使用yield return也能獲得同樣的結果。修改GetList方法為:
static IEnumerable<int> GetList(int count) { for (int i = 0; i < count; i++) { yield return r.Next(10); } }
通過斷點調試發現:客戶端每顯示一個集合中的元素,都會到GetList方法去獲取集合元素。
使用yield return獲取集合,并遍歷。
class Program { public static Random r = new Random(); static IEnumerable<int> GetList(int count) { for (int i = 0; i < count; i++) { yield return r.Next(10); } } static void Main(string[] args) { foreach(int item in GetList(5)) Console.WriteLine(item); Console.ReadKey(); } }
生成項目,并用Reflector反編譯可執行文件。在.NET 1.0版本下查看GetList方法,發現該方法返回的是一個GetList類的實例。原來yield return是"語法糖",其本質是生成了一個GetList的實例。
那GetList實例是什么呢?點擊Reflector中<GetList>鏈接查看。
原來GetList類實現了IEnumerable和IEnumerator的泛型、非泛型接口
yield return返回的集合之所以能被迭代、遍歷,是因為GetList內部有迭代器
yield return之所以能實現"按需供給",是因為GetList內部有一個_state字段記錄這上次的狀態
接下來,就模擬GetList,我們自定義一個GetRandomNumbersClass類,使之能達到yield return相同的效果。
using System; using System.Collections; using System.Collections.Generic; namespace ConsoleApplication2 { class Program { public static Random r = new Random(); static IEnumerable<int> GetList(int count) { GetRandomNumbersClass ret = new GetRandomNumbersClass(); ret.count = count; return ret; } static void Main(string[] args) { foreach(int item in GetList(5)) Console.WriteLine(item); Console.ReadKey(); } } class GetRandomNumbersClass : IEnumerable<int>, IEnumerator<int> { public int count;//集合元素的數量 public int i; //當前指針 private int current;//存儲當前值 private int state;//保存遍歷的狀態 #region 實現IEnumerator接口 public int Current { get { return current; } } public bool MoveNext() { switch (state) { case 0: //即為初始默認值 i = 0;//把指針調向0 goto case 1; break; case 1: state = 1;//先設置原狀態 if (!(i < count))//如果指針大于等于當前集合元素數量 { return false; } current = Program.r.Next(10); state = 2; //再設置當前狀態 return true; break; case 2: //再次遍歷如果state值為2 i++;//指針再移動一位 goto case 1; break; } return false; } //被顯式調用的屬性 object IEnumerator.Current { get { return Current; } } public void Reset() { throw new NotImplementedException(); } public void Dispose() { } #endregion #region 實現IEnumerable的泛型和非泛型 public IEnumerator<int> GetEnumerator() { return this; } //被顯式調用的屬性 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } #endregion } }
關于GetRandomNumbersClass類:
count表示集合的長度,可以在客戶端賦值。當調用迭代器的MoveNext方法,需要把count和當前位置比較,以決定是否可以再向前移動。
字段i相當于索引,指針每次移動一位,i需要自增1
current表示當前存儲的值,外部通過IEnumerator.Current屬性訪問
迭代器的MoveNext方法是關鍵:
state字段是整型,表示產生集合過程中的3種狀態
當state為0的時候,說明是初始狀態,把索引位置調到0,并跳轉到state為1的部分
當state為1的時候,首先把狀態設置為1,然后判斷索引的位置有沒有大于或等于集合的長度,接著產生集合元素,把state設置為2,并最終返回true
當sate為2的時候,也就是迭代器向前移動一位,再次執行MonveNext方法的時候,跳轉到state為2的語句塊部分,把索引位置自增1,再跳轉到state為1的語句塊中,產生新的集合元素
如此循環
假設在一個無限循環的環境中獲取一個int類型的集合,在客戶端通過某個條件來終止循環。
class Program { static Random rand = new Random(); static IEnumerable<int> GetList() { while (true) { yield return rand.Next(100); } } static void Main(string[] args) { foreach (int item in GetList()) { if (item%10 == 0) { break; } Console.WriteLine(item); } Console.ReadKey(); } }
以上,當集合元素可以被10整除的時候,就終止循環。終止循環的時機是在循環遍歷的時候。
如果用yield break,就可以在獲取集合的時候,當符合某種條件就終止獲取集合。
class Program { static Random rand = new Random(); static IEnumerable<int> GetList() { while (true) { int temp = rand.Next(100); if (temp%10 == 0) { yield break; } yield return temp; } } static void Main(string[] args) { foreach (int item in GetList()) { Console.WriteLine(item); } Console.ReadKey(); } }
總結:
yield return能返回一個"按需供給"的集合
yield return是"語法糖",其背后是一個實現了IEnuerable,IEnumerator泛型、非泛型接口的類,該類維護著一個狀態字段,以保證yield return產生的集合能"按需供給"
yield break配合yield return使用,當產生集合達到某種條件的時候使用yield break,以終止繼續創建集合
關于“C#中的yield關鍵字怎么用”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“C#中的yield關鍵字怎么用”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。