Daher stoße ich häufig auf diese Situation ... in Do.Something(...)
der eine Nullsammlung zurückgegeben wird, wie folgt:
int[] returnArray = Do.Something(...);
Dann versuche ich, diese Sammlung so zu verwenden:
foreach (int i in returnArray)
{
// do some more stuff
}
Ich bin nur neugierig, warum kann eine foreach-Schleife nicht mit einer Nullsammlung arbeiten? Es scheint mir logisch, dass 0 Iterationen mit einer Nullsammlung ausgeführt werden ... stattdessen wird a ausgelöst NullReferenceException
. Weiß jemand warum das sein könnte?
Das ist ärgerlich, da ich mit APIs arbeite, bei denen nicht klar ist, was sie zurückgeben, sodass ich if (someCollection != null)
überall ...
Bearbeiten: Vielen Dank an alle für die Erklärung dieser foreach
Verwendung GetEnumerator
und wenn es keinen Enumerator gibt, der abgerufen werden kann, würde der foreach fehlschlagen. Ich frage mich wohl, warum die Sprache / Laufzeit keine Nullprüfung durchführen kann oder will, bevor ich den Enumerator greife. Es scheint mir, dass das Verhalten immer noch gut definiert wäre.
null
Wert angegeben wird. Schlagen Sie dies auch nur fürforeach
Schleifen oder andere Anweisungen vor?Antworten:
Die kurze Antwort lautet: "So haben es die Compiler-Designer entworfen." Realistisch gesehen ist Ihr Sammlungsobjekt jedoch null, sodass der Compiler den Enumerator nicht dazu bringen kann, die Sammlung zu durchlaufen.
Wenn Sie so etwas wirklich tun müssen, versuchen Sie es mit dem Null-Koaleszenz-Operator:
quelle
GetEnumerator
das Ergebnis aufzurufenEine
foreach
Schleife ruft dieGetEnumerator
Methode auf.Wenn die Auflistung ist
null
, führt dieser Methodenaufruf zu aNullReferenceException
.Es ist eine schlechte Praxis, eine
null
Sammlung zurückzugeben. Ihre Methoden sollten stattdessen eine leere Sammlung zurückgeben.quelle
int[] returnArray = Do.Something() ?? new int[] {};
... ?? new int[0]
.Es gibt einen großen Unterschied zwischen einer leeren Sammlung und einem Nullverweis auf eine Sammlung.
Wenn Sie
foreach
intern verwenden, ruft dies die GetEnumerator () -Methode des IEnumerable auf . Wenn die Referenz null ist, wird diese Ausnahme ausgelöst.Es ist jedoch durchaus gültig, ein leeres
IEnumerable
oder zu habenIEnumerable<T>
. In diesem Fall "iteriert" foreach nichts (da die Sammlung leer ist), wirft aber auch nicht, da dies ein absolut gültiges Szenario ist.Bearbeiten:
Persönlich würde ich eine Erweiterungsmethode empfehlen, wenn Sie dies umgehen müssen:
Sie können dann einfach anrufen:
quelle
Es wird lange zurück beantwortet, aber ich habe versucht, dies auf die folgende Weise zu tun, um nur eine Nullzeigerausnahme zu vermeiden, und kann für jemanden nützlich sein, der den C # -Nullprüfungsoperator verwendet?
quelle
null
) Verallgemeinerung der gesamten Schleife auf das LCD vonEnumerable
(wie bei Verwendung??
) beinhaltet, b) das Hinzufügen einer Erweiterungsmethode zu jedem Projekt erfordert; und c) zunächst das Vermeiden vonnull
IEnumerable
s (Pffft! Puh-LEAZE! SMH. ) erfordern .Eine weitere Erweiterungsmethode, um dies zu umgehen:
Auf verschiedene Arten konsumieren:
(1) mit einer Methode, die akzeptiert
T
:(2) mit einem Ausdruck:
(3) mit einer mehrzeiligen anonymen Methode
quelle
Console.WriteLine
ist nur ein Beispiel für eine Methode, die ein Argument (einAction<T>
) akzeptiert . Die Punkte 1, 2 und 3 zeigen Beispiele für die Übergabe von Funktionen an die.ForEach
Erweiterungsmethode.null
) verallgemeinern die gesamte Schleife zum LCDEnumerable
(wie die Verwendung??
würde ), b) erfordern, dass jedem Projekt eine Erweiterungsmethode hinzugefügt wird, oder c) dass zunächstnull
IEnumerable
s (Pffft! Puh-LEAZE! SMH.) vermieden wird (cuznull
bedeutet N / A, während leere Liste bedeutet, dass es anwendbar ist, aber ist Derzeit gut leer !, dh ein Mitarbeiter könnte Provisionen haben, die für Nicht-Verkäufe nicht zutreffend oder für Verkäufe leer sind.Schreiben Sie einfach eine Erweiterungsmethode, um Ihnen zu helfen:
quelle
Weil eine Nullsammlung nicht dasselbe ist wie eine leere Sammlung. Eine leere Sammlung ist ein Sammlungsobjekt ohne Elemente. Eine Nullsammlung ist ein nicht vorhandenes Objekt.
Hier ist etwas zu versuchen: Deklarieren Sie zwei Sammlungen jeglicher Art. Initialisieren Sie eine normalerweise so, dass sie leer ist, und weisen Sie der anderen den Wert zu
null
. Versuchen Sie dann, beiden Sammlungen ein Objekt hinzuzufügen, und sehen Sie, was passiert.quelle
Es ist die Schuld von
Do.Something()
. Die beste Vorgehensweise wäre hier, ein Array der Größe 0 (das ist möglich) anstelle einer Null zurückzugeben.quelle
Denn hinter den Kulissen
foreach
erwirbt der einen Enumerator, der dem entspricht:quelle
null
Referenzen dasselbe argumentieren , z. B. beim Zugriff auf Mitglieder. In der Regel ist dies ein Fehler, und wenn dies nicht der Fall ist, ist es einfach genug, dies beispielsweise mit der Erweiterungsmethode zu behandeln, die ein anderer Benutzer als Antwort angegeben hat.Ich denke, die Erklärung, warum eine Ausnahme ausgelöst wird, ist mit den hier gegebenen Antworten sehr klar. Ich möchte nur die Art und Weise ergänzen, wie ich normalerweise mit diesen Sammlungen arbeite. Weil ich die Sammlung manchmal mehrmals benutze und jedes Mal testen muss, ob sie null ist. Um dies zu vermeiden, mache ich Folgendes:
Auf diese Weise können wir die Sammlung so oft verwenden, wie wir möchten, ohne die Ausnahme zu befürchten, und wir verschmutzen den Code nicht mit übermäßigen bedingten Anweisungen.
Die Verwendung des Nullprüfungsoperators
?.
ist ebenfalls ein guter Ansatz. Bei Arrays (wie im Beispiel in der Frage) sollte es jedoch vorher in List umgewandelt werden:quelle
ForEach
Methode zu haben, ist eines der Dinge, die ich in einer Codebasis hasse.quelle