Wie erhält man in C # einen generischen Enumerator aus einem bestimmten Array?
Im folgenden Code MyArray
befindet sich ein Array von MyType
Objekten. Ich möchte MyIEnumerator
in der gezeigten Weise erhalten, aber es scheint, dass ich einen leeren Enumerator erhalte (obwohl ich das bestätigt habe MyArray.Length > 0
).
MyType[] MyArray = ... ;
IEnumerator<MyType> MyIEnumerator = MyArray.GetEnumerator() as IEnumerator<MyType>;
c#
arrays
generics
ienumerator
JaysonFix
quelle
quelle
Antworten:
Funktioniert mit 2.0+:
Funktioniert mit 3.5+ (ausgefallenes LINQy, etwas weniger effizient):
quelle
LINQ/Cast
hat ganz anderes Laufzeitverhalten, da jedes Element des Arrays wird durch einen zusätzlichen Satz übergeben werdenMoveNext
undCurrent
enumerator Rundfahrten, und diese Leistung beeinträchtigen könnte , wenn das Array ist riesig. In jedem Fall kann das Problem vollständig und einfach vermieden werden, indem zunächst der richtige Enumerator ermittelt wird (dh mit einer der beiden in meiner Antwort gezeigten Methoden).myArray.Cast<MyType>().GetEnumerator()
in Ihrer innersten Schleife verwenden, kann dies Sie selbst bei winzigen Arrays erheblich verlangsamen.Sie können selbst entscheiden, ob das Casting hässlich genug ist, um einen fremden Bibliotheksaufruf zu rechtfertigen:
Der Vollständigkeit halber sollte man auch beachten, dass das Folgende nicht korrekt ist - und zur Laufzeit abstürzt -, da
T[]
die nicht generischeIEnumerable
Schnittstelle für ihre Standardimplementierung (dh nicht explizite) von ausgewählt wirdGetEnumerator()
.Das Rätsel ist, warum nicht
SZGenericArrayEnumerator<T>
vonSZArrayEnumerator
einer internen Klasse geerbt wird, die derzeit als "versiegelt" gekennzeichnet ist, da dadurch der (kovariante) generische Enumerator standardmäßig zurückgegeben werden kann.quelle
((IEnumerable<int>)arr)
aber nur einen Satz von Klammern(IEnumerator<int>)arr
?Da ich kein Casting mag, ein kleines Update:
quelle
your_array.AsEnumerable()
überhaupt nicht kompiliert, da erAsEnumerable()
nur für Instanzen von Typen verwendet werden kann, die implementiert werdenIEnumerable
.Um es so sauber wie möglich zu machen, lasse ich den Compiler gerne die ganze Arbeit machen. Es gibt keine Abgüsse (also ist es tatsächlich typsicher). Es werden keine Bibliotheken von Drittanbietern (System.Linq) verwendet (kein Laufzeitaufwand).
// Und um den Code zu verwenden:
Dies nutzt einige Compiler-Magie, die alles sauber hält.
Der andere zu beachtende Punkt ist, dass meine Antwort die einzige Antwort ist, die eine Überprüfung zur Kompilierungszeit durchführt.
Wenn sich bei einer der anderen Lösungen der Typ von "arr" ändert, wird der aufrufende Code kompiliert und schlägt zur Laufzeit fehl, was zu einem Laufzeitfehler führt.
Meine Antwort führt dazu, dass der Code nicht kompiliert wird und ich daher weniger Chancen habe, einen Fehler in meinem Code zu versenden, da dies mir signalisieren würde, dass ich den falschen Typ verwende.
quelle
Foo[]
implementiert wirdIEnumerable<Foo>
, aber wenn sich dies jemals ändert, wird es zur Kompilierungszeit nicht erkannt. Explizite Casts sind niemals kompilierungssicher. Ordnen Sie stattdessen ein Array zu oder geben Sie es zurück, da IEnumerable <Foo> die implizite Umwandlung verwendet, die für die Kompilierungszeit geeignet ist.var foo = (int)new object()
. Es kompiliert einwandfrei und stürzt zur Laufzeit ab.YourArray.OfType (). GetEnumerator ();
kann etwas besser abschneiden, da nur der Typ überprüft und nicht gegossen werden muss.
quelle
OfType<..type..>()
- zumindest in meinem Falldouble[][]
quelle
Sie können natürlich nur Ihren eigenen generischen Enumerator für Arrays implementieren.
Dies entspricht mehr oder weniger der .NET-Implementierung von SZGenericArrayEnumerator <T>, wie von Glenn Slayden erwähnt. Sie sollten dies natürlich nur tun, wenn dies die Mühe wert ist. In den meisten Fällen ist dies nicht der Fall.
quelle