Wiem, jak zaimplementować nieogólne IEnumerable, na przykład:
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();
}
}
}
Jednak zauważam również, że IEnumerable ma wersję ogólną, IEnumerable<T>
, ale nie mogę dowiedzieć się, jak ją zaimplementować.
Jeśli dodam using System.Collections.Generic;
do moich dyrektyw using, a następnie zmienię:
class MyObjects : IEnumerable
do:
class MyObjects : IEnumerable<MyObject>
Następnie kliknij prawym przyciskiem myszy IEnumerable<MyObject>
i wybierz Implement Interface => Implement Interface
, Visual Studio z pomocą dodaje następujący blok kodu:
IEnumerator<MyObject> IEnumerable<MyObject>.GetEnumerator()
{
throw new NotImplementedException();
}
Zwracanie nieogólnego obiektu IEnumerable z GetEnumerator();
metody nie działa tym razem, więc co mam tutaj umieścić? Interfejs CLI ignoruje teraz nieogólną implementację i kieruje się bezpośrednio do wersji ogólnej, gdy próbuje wyliczyć moją tablicę podczas pętli foreach.
this.GetEnumerator()
a zwykłym zwracaniemGetEnumerator()
?Collection<MyObject>
możesz dziedziczyć po, a wtedy nie będziesz musiał pisać żadnego niestandardowego kodu.List<T>
i wdrożyć,IEnumerable<T>
jak pokazano w Twojej odpowiedzi.Prawdopodobnie nie chcesz jawnej implementacji
IEnumerable<T>
(co pokazałeś).Zazwyczaj wzór jest do użytku
IEnumerable<T>
„sGetEnumerator
w wyraźnej realizacjiIEnumerable
:źródło
IEnumerable
jest zbędna (IEnumerable<T>
już po niej dziedziczy).Dlaczego robisz to ręcznie?
yield return
automatyzuje cały proces obsługi iteratorów. (Pisałem też o tym na swoim blogu , włączając w to spojrzenie na kod wygenerowany przez kompilator).Jeśli naprawdę chcesz to zrobić sam, musisz również zwrócić ogólny moduł wyliczający. Nie będziesz już mógł używać
ArrayList
żadnego, ponieważ nie jest to typowe.List<MyObject>
Zamiast tego zmień go na . To oczywiście zakłada, żeMyObject
w swojej kolekcji masz tylko obiekty typu (lub typy pochodne).źródło
yield return
. Błędnie założyłem, że było jakieś niestandardowe przetwarzanie.Jeśli pracujesz z rodzajami, użyj listy zamiast ArrayList. Lista zawiera dokładnie taką metodę GetEnumerator, jakiej potrzebujesz.
źródło
zmienić mylist w a
List<MyObject>
, jest jedną z opcjiźródło
Zauważ, że
IEnumerable<T>
już zaimplementowane przezSystem.Collections
to inne podejście polega na wyprowadzeniu TwojejMyObjects
klasy zSystem.Collections
klasy bazowej ( dokumentacja ):Możemy później uczynić nasz własny implementacja zastąpić wirtualne
System.Collections
metody zapewniające zachowanie niestandardowe (tylkoClearItems
,InsertItem
,RemoveItem
, aSetItem
wraz zEquals
,GetHashCode
iToString
odObject
). W przeciwieństwie do tego,List<T>
który nie jest zaprojektowany tak, aby był łatwo rozszerzalny.Przykład:
Należy pamiętać, że jazda z
collection
zalecana jest tylko w przypadku, gdy potrzebne jest niestandardowe zachowanie kolekcji, co rzadko się zdarza. zobacz użycie .źródło