1. 程式人生 > 實用技巧 >[c#]foreach的原理

[c#]foreach的原理

foreach本質上是迭代的使用,學習過程中發現它和c中的地址定位差不多,也是通過遊標的不斷移動獲取當前所指向的資料。迭代器可以用一種方式,順序訪問集合型別(陣列、字典、佇列....)元素。

簡單演示一下:

有一個介面IThrowable,其下有兩個繼承類GrenadeDarts;類Hand下有一個數組,其中包含GrenadeDarts

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關鍵字的存在,我們將yieldreturn結合一下,就可以將程式碼縮簡為:

class Hand:IEnumerable

{

  //優化寫法

    public IEnumerator GetEnumerator()

    {

        /*

         * 將yield以前的程式碼分配到MoveNext方法中

         * 將return後的資料分配到Current屬性中

         */

        for (int i = 0; i < AllObject.Length; i++)

        {

            yield return AllObject[i];//返回資料 退出方法

        }

   }

}

這樣我們就可以將繁瑣的HandEnumerator 一起省去了。

執行測試下: