close

1.尋訪collection元素

無論物件類型是陣列,串列...資料結構都會用到尋訪原素這個操作,於是.NET Framework將這些基本共通操作定義於兩個Interface中,

使我扪可以用同一組方法來操作各種不同collection物件。 

這兩個Interface就是: 

a. IEnumerable

b. IEnumerator

 

2.IEnumerable and IEnumerator

IEnumerator定義了一組列舉器的巡覽操作,這操作是read only(並不會改變目前物件的內容),而且巡覽方向是單一的(只能取下一個元素)。 

定義如下:

public interface IEnumerator

{

   object Current{ get; }  //傳回目前的元素

   bool MoveNext(); //移至下一個元素,若傳回false則表示沒有下一個元素

   void Reset(); //重新指向第一個元素

}

 

不過 collection 通常不實做IEnumerator,而是透過實做IEnumerable介面來提供列舉器。 

定義如下:

public interface IEnumerable

{

   IEnumerator GetEnumerator(); //取得列舉器

}

如上只定義一個GetEnumerator()方法,傳回IEnumerator 物件,所以IEnumerable基本上扮演提供列舉器之角色,

而collection類型(array,list...)都有實做IEnumerable介面,故它們(Array,List....)都是列舉器的提供者。

 

example(示範如何透過 IEnumerator 尋訪collection中每一個元素)

擷取  

 

note: 

1.IEnumerator enumrt = fruits.GetEnumerator();

之所以可以通過編譯是因為C#Array都繼承System.Array類別,而System.Array類別都有實做IEnumerable介面,故可以呼叫GetEnumerator()方法。

2.enumrt.Current傳回型別是object,故須手動轉型。

3.其實可以用foreach來取代,因為froeach可以尋訪任何"可列舉的"物件,符合以下任一條件都稱為符合可列舉之物件:

   a.實做IEnumerable or IEnumerator

   b.回傳之型別有實做IEnumerator or GetEnumerator<T>

ex.

string[] fruits = {"Apple","Banana","Orange"};

froeach(var item in fruits)

{

   response.write(item);

}

 

3.IEnumerable<T> and IEnumerator<T>

定義列舉操作也有泛型版本,且泛型版本比非泛型更常用也更方便(不用手動轉型)。

底下為此兩個泛型介面之定義:

public interface IEnumerable<out T> : IEnumerable

{

   IEnumerator<T> GetEnumerator(); // 取得列舉器

}

 

public interface IEnumerator<out T> : IDisposable , IEnumerator

{

   T Current{ get; }

}

 

note:

1.泛型參數T前有個out,out代表告訴編譯器,型別參數T在此介面中只能用於輸出(方法回傳值),不能當成輸入參數用。

2.GetEnumerator方法在呼叫時不需要,也不可以傳入泛型參數T,但注意其回傳型別仍為IEnumerator<T>。 

IEnumerator<string>  enumrt = fruits.GetEnumerator<string>(); 

上面這行編譯會失敗,因為呼叫GetEnumerator方法不需要傳入泛型型別。

解法: 把fruits陣列手動轉成IEnumerable<string>,如此便可以呼叫GetEnumerator方法,來取得泛型版本的IEnumerator<string>物件。

example:

擷取  

 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 melomelo1988 的頭像
    melomelo1988

    melo 唐

    melomelo1988 發表在 痞客邦 留言(0) 人氣()