實現IEnumerable接口的類,可以支持foreach循環遍歷對象的集合元素
IEnumerable:
IEnumerator GetEnumerator()
返回可循環訪問集合的枚舉數。
IEnumerator:
object Current
獲取集合中的當前元素。
bool MoveNext()
將枚舉數推進到集合的下一個元素。
如果枚舉數 成功地推進到下一個元素,則為 true;如果枚舉數越過集合的結尾,則為 false。
void Reset()
將枚舉數設置為其初始位置,該位置位於集合中第一個元 素之前。
在現實應用中,對於集合以及枚舉這些集合的需求非常普遍, 因此在.NET中集合所依賴的接口被設計為公共的。想要實現對象的枚舉就必須繼承IEnumerable接口。
public interface IEnumerable
{
public IEnumerator GetEnumerator();
}
它 只有一個成員:GetEnumerator方法。該方法返回一個實際的枚舉器(enumerator)對象。那麼要定義一個枚舉器就要必 須實現IEnumrator接口:
public interface IEnumerator
{
public Boolean MoveNext();
public Object Current { get; }
public void Reset();
}
這裡我不想把MSDN上的解釋在重復一遍,我只是提出一個問題,也就是說如果我們希望一個類型支持 枚舉特性,那麼我們就必須還要額外定義一個輔助類型來實現IEnumerator的所有方法。這個輔助類型通常被定義為一個Nested class聲明在主類內部。這樣在實現的時候我們發現,在app調用GetEnumerator()方法時,我們需要構造一個輔助類型的實例作為返回值。 這時我們有兩種做法:
這 的確提供了一定的靈活性給用戶, 在app想要枚舉某個實例的數據集合時,也可以有兩種方法:
對於foreach,我想提兩句,要想使用它所必須滿足的條件:
答 案:采用這種間接的方式是為了提高靈活性。你可以利用IEnumerator來決定如何展示你想要暴露的內部數據給客戶。當然你可以在一個類型中同時實現 這兩個接口:class MyArrayData : IEnumerable, IEnumerator { ... };這樣可以節省了一些創建輔助類型從而帶來的CPU和Memory開銷。一般建議在如下情況時,使用這種結合的方法:
答案:由於值類型在傳入ArrayList這樣的集合容器中時,需要 box,在傳出的時候需要unbox。經過很多驗證,這種操作時非常耗時的。因此,我們可以在實現標准的枚舉方法的時候,可以在暴露一些自定義的 GetEnumerator, MoveNext和Current方法(其實, 標准的接口只是調用自定義的接口而已的一個wrapper方法)。這樣既可以在自己的方法中避免了不必要的裝箱和拆箱操作(用自定義方法,而不能使用 foreach語句),又可以被約定俗成的foreach句法所調用(當然,這種情況下就不能避免box和unbox了)。