Come implementare IEnumerable

So come implementare l’IEnumerable non generico, come questo:

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(); } } } 

Tuttavia noto anche che IEnumerable ha una versione generica, IEnumerable , ma non riesco a capire come implementarlo.

Se aggiungo using System.Collections.Generic; alle mie direttive di utilizzo, e quindi cambio:

 class MyObjects : IEnumerable 

a:

 class MyObjects : IEnumerable 

Quindi fare clic con il pulsante destro del mouse su IEnumerable e selezionare Implement Interface => Implement Interface , Visual Studio aggiunge in modo utile il seguente blocco di codice:

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

Restituzione dell’object IEnumerable non generico da GetEnumerator(); metodo non funziona questa volta, quindi cosa metto qui? La CLI ora ignora l’implementazione non generica e punta direttamente alla versione generica quando tenta di enumerare attraverso il mio array durante il ciclo foreach.

Se si sceglie di utilizzare una raccolta generica, come List anziché ArrayList , si scoprirà che l’ List fornirà enumeratori generici e non generici che è ansible utilizzare.

 using System.Collections; class MyObjects : IEnumerable { List mylist = new List(); public MyObject this[int index] { get { return mylist[index]; } set { mylist.Insert(index, value); } } public IEnumerator GetEnumerator() { return mylist.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return this.GetEnumerator(); } } 

Probabilmente non vuoi un’implementazione esplicita di IEnumerable (che è ciò che hai mostrato).

Il solito schema consiste nell’utilizzare GetEnumerator di IEnumerable nell’implementazione esplicita di IEnumerable:

 class FooCollection : IEnumerable, IEnumerable { SomeCollection foos; // Explicit for IEnumerable because weakly typed collections are Bad System.Collections.IEnumerator IEnumerable.GetEnumerator() { // uses the strongly typed IEnumerable implementation return this.GetEnumerator(); } // Normal implementation for IEnumerable IEnumerator 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 or T[], your choice. } // or, as pointed out: return this.foos.GetEnumerator(); } } 

Perché lo fai manualmente? yield return automatizza l’intero processo di gestione degli iteratori. (Ne ho scritto anche sul mio blog , incluso uno sguardo al codice generato dal compilatore).

Se vuoi davvero farlo da solo, devi anche restituire un enumeratore generico. Non sarai più in grado di utilizzare un ArrayList poiché non è generico. Sostituirlo con un List . Ovviamente si presume che nella raccolta siano presenti solo oggetti di tipo MyObject (o tipi derivati).

Se lavori con generici, usa List invece di ArrayList. L’Elenco ha esattamente il metodo GetEnumerator di cui hai bisogno.

 List myList = new List(); 

rendere mylist in una List , è un’opzione