[c#]foreach的原理
阿新 • • 發佈:2020-12-08
foreach本質上是迭代的使用,學習過程中發現它和c中的地址定位差不多,也是通過遊標的不斷移動獲取當前所指向的資料。迭代器可以用一種方式,順序訪問集合型別(陣列、字典、佇列....)元素。
簡單演示一下:
有一個介面IThrowable,其下有兩個繼承類Grenade和Darts;類Hand下有一個數組,其中包含Grenade和Darts。
class Hand:IEnumerable { public IThrowable[] AllObject { get; set; } }
Main中例項化一個Hand物件:
static void Main(string[] args) { Hand hand= new Hand() { AllObject = new IThrowable[2]//可投擲物介面,下有兩個類手雷和飛鏢 { new Grenade(), new Darts() } }; }
此時我們使用迭代器來獲取Hand中的所有物件,所以Main應該是:
static void Main(string[] args) { Hand hand = new Hand() { AllObject = new IThrowable[2]//可投擲物介面,下有兩個類手雷和飛鏢 { new Grenade(), new Darts() } }; //1.獲取迭代器 IEnumerator iterator = hand.GetEnumerator(); //2.移動到下一個元素 while (iterator.MoveNext()) { //3.獲取元素 Console.WriteLine(iterator.Current); } Console.ReadKey(); }
到這裡就會發現迭代器的使用主要就是在GetEnumerator()這個方法,它的返回值是列舉器,也就是我們所理解的遊標。所以在Hand中我們需要實現下它的功能:
class Hand:IEnumerable { public IThrowable[] AllObject { get; set; } //傳統寫法 public IEnumerator GetEnumerator() { //建立迭代器物件 return new HandEnumerator() { Target = AllObject }; } }
這裡的HandEnumerator就是生成一個列舉器所用的迭代器
//傳統寫法 //類的迭代器,以Hand為例 class HandEnumerator : IEnumerator { public IThrowable[] Target { get; set; } private int index; //獲取當前資料 public object Current { get { return Target[index]; } } //移動到下一個資料 public bool MoveNext() { index++; return index <= Target.Length - 1; } //未用到暫時不寫 public void Reset() { } }
注意上面所註釋的是傳統的建立迭代器和使用方法,由於有yield關鍵字的存在,我們將yield和return結合一下,就可以將程式碼縮簡為:
class Hand:IEnumerable { //優化寫法 public IEnumerator GetEnumerator() { /* * 將yield以前的程式碼分配到MoveNext方法中 * 將return後的資料分配到Current屬性中 */ for (int i = 0; i < AllObject.Length; i++) { yield return AllObject[i];//返回資料 退出方法 } } }
這樣我們就可以將繁瑣的HandEnumerator 一起省去了。
執行測試下: