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