天天看點

能用foreach周遊通路的對象需要實作____接口或聲明____方法的類型

之前面試看到一個這樣的筆試題,當時隻知道List和Dictionary類型可以用foreach周遊,但他兩也沒什麼共同點啊。List是有序的,但Dictionary是無序的。回來在網上查了下才發現,他們都實作了IEnumerable接口,申明了GetEnumerator方法。打開源碼後發現确實如此:

能用foreach周遊通路的對象需要實作____接口或聲明____方法的類型
能用foreach周遊通路的對象需要實作____接口或聲明____方法的類型

接下來就詳細寫一下自定義的類如果用foreach周遊。

首先定義一個Item類

public class Item
{
    public int Id;
    public string Name;
    public int Price;

    public Item(int id, string name, int price)
    {
        Id = id;
        Name = name;
        Price = price;
    }
}
           

接下來要寫的類就是暴漏給外部調用,實作了IEnumerable的ItemList.

public class ItemList : IEnumerable
{
    private Item[] items;

    public int Count
    {
        get { return items.Length; }
    }

    public ItemList(Item[] _items)
    {
        items = _items;
    }
    public Item this[int index]
    {
        get { return items[index]; }
    }
    public IEnumerator GetEnumerator()
    {
        for (int i = 0; i < items.Length; i++)
        {
            yield return items[i];
        }
    }
    //public IEnumerator GetEnumerator()
    //{
    //    return items.GetEnumerator();
    //}
}           

這裡可以不實作IEnumerable接口,但是GetEnumerator方法必須申明,不然在調用時會報錯。而GetEnumerator方法,這裡寫了前兩種方法。一種是通過for循環依次傳回,一種是因為[]本身就實作了IEnumerable,所有可以直接用它的GetEnumerator。

然後寫一個測試代碼:

ItemList itemList=new ItemList(new Item[]{new Item(1,"apple",3),new Item(2,"banana",3)  });
        foreach (Item item in itemList)
        {
            Debug.Log(item.Id+"__"+item.Name+"__"+item.Price);
        }           

這樣就可以通過foreach周遊自己寫的ItemList類了。

還有第三種方法,就是自己重寫一個實作IEnumerator的類

public class ItemListEnumerator : IEnumerator
{
    private int index = -1;
    private ItemList itemList;

    public ItemListEnumerator(ItemList _itemList)
    {
        itemList = _itemList;
    }

    public object Current
    {
        get { return itemList[index]; }
    }

    public bool MoveNext()
    {
        index++;
        return index < itemList.Count;
    }

    public void Reset()
    {
        index = -1;
    }
}           

然後修改ItemList中的GetEnumerator方法

public IEnumerator GetEnumerator()
    {
       return new ItemListEnumerator(this);
    }           

至此讓一個自定義類可以被foreach周遊的三種方法都有了。而寫到這裡,對IEnumerator做一些猜想。因為在寫協程時,傳回的參數同樣是IEnumerator類型。而這裡相當于每調用一次,就像Next實作的一樣,把指針指向了下一個元素。再深究,感覺就是IEnumerator自身到底是一個什麼類型的東西了,起什麼作用。

最後附上兩個連結,我這篇相當于對這兩位筆者博文的結合。

https://blog.csdn.net/qq_39081464/article/details/81023878

https://blog.csdn.net/zfq18317916225/article/details/50717751