2012-07-02 91 views
86

我知道如何實現非通用IEnumerable的,就像這樣:如何實現IEnumerable <T>

using System; 
using System.Collections; 

namespace ConsoleApplication33 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyObjects myObjects = new MyObjects(); 
      myObjects[0] = new MyObject() { Foo = "Hello", Bar = 1 }; 
      myObjects[1] = new MyObject() { Foo = "World", Bar = 2 }; 

      foreach (MyObject x in myObjects) 
      { 
       Console.WriteLine(x.Foo); 
       Console.WriteLine(x.Bar); 
      } 

      Console.ReadLine(); 
     } 
    } 

    class MyObject 
    { 
     public string Foo { get; set; } 
     public int Bar { get; set; } 
    } 

    class MyObjects : IEnumerable 
    { 
     ArrayList mylist = new ArrayList(); 

     public MyObject this[int index] 
     { 
      get { return (MyObject)mylist[index]; } 
      set { mylist.Insert(index, value); } 
     } 

     IEnumerator IEnumerable.GetEnumerator() 
     { 
      return mylist.GetEnumerator(); 
     } 
    } 
} 

不過,我也注意到了IEnumerable有一個通用版本,IEnumerable<T>,但我無法弄清楚如何執行它。

如果我添加using System.Collections.Generic;我使用的指令,然後更改:

class MyObjects : IEnumerable 

到:

class MyObjects : IEnumerable<MyObject> 

,然後右鍵單擊IEnumerable<MyObject>,選擇Implement Interface => Implement Interface,Visual Studio的有益補充以下塊代碼:

IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator() 
{ 
    throw new NotImplementedException(); 
} 

Returni ng GetEnumerator();方法中的非通用IEnumerable對象此時不起作用,那麼我在這裏放置了什麼? CLI現在忽略了非泛型實現,並在foreach循環期間嘗試枚舉我的數組時通過泛型版本直接轉向。

謝謝

回答

107

如果您選擇使用泛型集合,如List<MyObject>代替ArrayList,你會發現List<MyObject>將提供您可以使用通用和非通用統計員。

using System.Collections; 

class MyObjects : IEnumerable<MyObject> 
{ 
    List<MyObject> mylist = new List<MyObject>(); 

    public MyObject this[int index] 
    { 
     get { return mylist[index]; } 
     set { mylist.Insert(index, value); } 
    } 

    public IEnumerator<MyObject> GetEnumerator() 
    { 
     return mylist.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return this.GetEnumerator(); 
    } 
} 
+0

在非泛型實現中,返回'this.GetEnumerator()'和簡單地返回'GetEnumerator()'有區別嗎? –

+0

@TannerSwett沒有區別。 –

20

你爲什麼手動做? yield return自動處理迭代器的整個過程。 (我也寫過關於它的on my blog,包括看看編譯器生成的代碼)。

如果你真的想自己做,你必須返回一個泛型枚舉器。您不能再使用ArrayList,因爲這是非通用的。改爲改爲List<MyObject>。這當然假定你的集合中只有MyObject(或派生類型)類型的對象。

+2

+1,應該注意的是,首選模式是實現通用接口並顯式實現非通用接口。產量回報是通用接口的最自然的解決方案。 – user7116

+4

除非OP將在枚舉器中進行一些處理,否則使用yield return只會增加另一個狀態機的開銷。 OP應該返回一個底層泛型集合提供的枚舉器。 –

+0

@MonroeThomas:你說得對。在寫關於「收益率回報」之前,我沒有仔細閱讀過這個問題。我錯誤地認爲有一些自定義處理。 –

0

化妝MYLIST爲List<MyObject>,是一種選擇

38

你可能不希望一個明確實施IEnumerable<T>(這是你出了什麼)。

通常的模式是使用的IEnumerable<T>的GetEnumerator在明確實現的IEnumerable的:

class FooCollection : IEnumerable<Foo>, IEnumerable 
{ 
    SomeCollection<Foo> foos; 

    // Explicit for IEnumerable because weakly typed collections are Bad 
    System.Collections.IEnumerator IEnumerable.GetEnumerator() 
    { 
     // uses the strongly typed IEnumerable<T> implementation 
     return this.GetEnumerator(); 
    } 

    // Normal implementation for IEnumerable<T> 
    IEnumerator<Foo> GetEnumerator() 
    { 
     foreach (Foo foo in this.foos) 
     { 
      yield return foo; 
      //nb: if SomeCollection is not strongly-typed use a cast: 
      // yield return (Foo)foo; 
      // Or better yet, switch to an internal collection which is 
      // strongly-typed. Such as List<T> or T[], your choice. 
     } 

     // or, as pointed out: return this.foos.GetEnumerator(); 
    } 
} 
+1

如果SomeCollection 尚未實現IEnumerable ,或者如果您需要在枚舉序列中返回之前對每個元素進行轉換或進行其他處理,則這是一個很好的解決方案。如果這兩個條件都不成立,那麼返回this.foos.GetEnumerator()可能會更高效。 –

+0

@MonroeThomas:同意。不知道OP使用的是什麼樣的集合。 – user7116

+4

好點。但是實現'IEnumerable'是多餘的('IEnumerable '已經從它繼承)。 – rsenna

3

如果使用泛型,使用列表,而不是ArrayList的工作。該列表具有您需要的GetEnumerator方法。

List<MyObject> myList = new List<MyObject>(); 
相關問題