在現實應用中,對於集合以及枚舉這些集合的需求非常普遍, 因此在.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了)。