In C # verwende ich LINQ und IEnumerable ein gutes Stück. Und alles ist gut und schön (oder zumindest meistens).
In vielen Fällen stelle ich jedoch fest, dass ich IEnumerable<X>
standardmäßig ein Leerzeichen benötige . Das heißt, ich würde gerne
for (var x in xs) { ... }
zu arbeiten, ohne eine Nullprüfung zu benötigen. Dies ist, was ich derzeit mache, abhängig vom größeren Kontext:
var xs = f() ?? new X[0]; // when xs is assigned, sometimes
for (var x in xs ?? new X[0]) { ... } // inline, sometimes
Nun, obwohl das oben Genannte für mich vollkommen in Ordnung ist - das heißt, wenn es beim Erstellen des Array-Objekts einen "zusätzlichen Aufwand" gibt, ist es mir einfach egal -, habe ich mich gefragt:
Gibt es in C # /. NET den Singleton "leerer unveränderlicher IEnumerable / IList"? (Und selbst wenn nicht, gibt es eine "bessere" Möglichkeit, den oben beschriebenen Fall zu behandeln?)
Java hat einen Collections.EMPTY_LIST
unveränderlichen Singleton - "gut typisiert" über Collections.emptyList<T>()
-, der diesem Zweck dient, obwohl ich nicht sicher bin, ob ein ähnliches Konzept überhaupt in C # funktionieren könnte, da Generika anders behandelt werden.
Vielen Dank.
public static class Array<T> { public static readonly T[] Empty = new T[0]; }
und es kann wie folgt aufgerufen werden :Array<string>.Empty
. Ich habe hier in CodeReview danach gefragt .Antworten:
Sie suchen
Enumerable.Empty<T>()
.In anderen Nachrichten ist die leere Java-Liste zum Kotzen, weil die List-Schnittstelle Methoden zum Hinzufügen von Elementen zur Liste bereitstellt, die Ausnahmen auslösen.
quelle
List
(eine Sammlung, auf die über den Index zugegriffen werden kann). DieseList
können nur gelesen werden. Und manchmal müssen Sie ein solches schreibgeschütztesList
Element mit dem Element Null zurückgeben. Also dieCollections.emptyList()
Methode. Sie können nicht einfach eine leere Iterable zurückgeben, da eine implementierte Schnittstelle angibt, dass die Methode eine Liste zurückgibt. Das große Problem ist, dass es keine ImmutableList-Schnittstelle gibt, die Sie zurückgeben können. Das gleiche Problem besteht in .NET:IList
Jedes kann schreibgeschützt sein.Enumerable.Empty<T>()
ist genau das.quelle
Array.Empty<T>()
ist diese genauer, da es sich um eine handeltIList<T>
. Es hat den glücklichen Vorteil, auch befriedigend zu seinIReadOnlyCollection<T>
. Natürlich, wo einIEnumerable<T>
tut genügen,Enumerable.Empty<T>()
passt perfekt.Array.Empty<T>
und zur Verfügung gestellt. :) Ungeachtet des Titels macht die Frage auf jeden Fall ausdrücklich klar, dass einIEnumerable<T>
für den Zweck gut ist.Ich denke du suchst
Enumerable.Empty<T>()
.Ein Singleton mit leeren Listen macht nicht so viel Sinn, da Listen oft veränderlich sind.
quelle
In Ihrem ursprünglichen Beispiel verwenden Sie ein leeres Array, um eine leere Aufzählung bereitzustellen. Bei der Verwendung von
Enumerable.Empty<T>()
rechts ist perfekt, es könnten auch andere Fälle: Wenn Sie verwenden müssen ein Array (oder dieIList<T>
Schnittstelle), können Sie die Methode verwenden ,Dies hilft Ihnen, unnötige Zuordnungen zu vermeiden.
Anmerkungen / Referenzen:
quelle
Ich denke, das Hinzufügen einer Erweiterungsmethode ist eine saubere Alternative, da sie mit Nullen umgehen können - so etwas wie:
public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> list) { return list ?? Enumerable.Empty<T>(); } foreach(var x in xs.EmptyIfNull()) { ... }
quelle
Microsoft hat "Any ()" wie folgt implementiert ( Quelle )
public static bool Any<TSource>(this IEnumerable<TSource> source) { if (source == null) throw new ArgumentNullException("source"); using (IEnumerator<TSource> e = source.GetEnumerator()) { if (e.MoveNext()) return true; } return false; }
Wenn Sie einen Aufruf auf dem Aufrufstapel speichern möchten, anstatt eine aufrufende Erweiterungsmethode zu
!Any()
schreiben, schreiben Sie diese drei Änderungen einfach neu:public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name) { if (source == null) throw new ArgumentNullException("source"); using (IEnumerator<TSource> e = source.GetEnumerator()) { if (e.MoveNext()) return false; //second change } return true; //third change }
quelle
Die Verwendung
Enumerable.Empty<T>()
mit Listen hat einen Nachteil. Wenn SieEnumerable.Empty<T>
den Listenkonstruktor übergeben, wird ein Array der Größe 4 zugewiesen. Wenn Sie dem Listenkonstruktor jedoch einCollection
Leerzeichen übergeben, erfolgt keine Zuordnung. Wenn Sie diese Lösung im gesamten Code verwenden, wird höchstwahrscheinlich eines derIEnumerable
s zum Erstellen einer Liste verwendet, was zu unnötigen Zuordnungen führt.quelle