Soweit ich weiß, FirstOrDefault()
kann die Methode in Linq einen anderen Default
Wert als null zurückgeben. Was ich nicht herausgefunden habe, ist, welche anderen Dinge als null von dieser (und ähnlichen) Methode zurückgegeben werden können, wenn das Abfrageergebnis keine Elemente enthält. Gibt es eine bestimmte Möglichkeit, dies so einzurichten, dass, wenn für eine bestimmte Abfrage kein Wert vorhanden ist, ein vordefinierter Wert als Standardwert zurückgegeben wird?
142
YourCollection.FirstOrDefault()
könnten SieYourCollection.DefaultIfEmpty(YourDefault).First()
zum Beispiel verwenden.MyCollection.Last().GetValueOrDefault(0)
. Andernfalls ist die Antwort von @Jon Skeet unten IMO korrekt.Antworten:
Allgemeiner Fall, nicht nur für Werttypen:
Auch dies kann sagen , nicht wirklich , ob es war alles in Ihrer Sequenz, oder wenn der erste Wert der Standard ist.
Wenn Sie sich dafür interessieren, könnten Sie so etwas tun
und verwenden als
obwohl, wie Mr. Steak betont, dies genauso gut von getan werden könnte
.DefaultIfEmpty(...).First()
.quelle
<T>
in ihren Namen, aber schwerwiegender ist, dassvalue == default(T)
das nicht funktioniert (denn wer weiß, obT
für Gleichheit verglichen werden kann?)EqualityComparer<T>.Default.Equals(value, default(T))
, um das Boxen zu vermeiden und eine Ausnahme zu vermeiden, wenn der Wertnull
Nein. Oder besser gesagt, es wird immer der Standardwert für den Elementtyp ... zurückgegeben, der entweder eine Nullreferenz, der Nullwert eines nullbaren Werttyps oder der natürliche Wert "alle Nullen" für einen nicht nullbaren Werttyp ist.
Für Referenztypen können Sie einfach Folgendes verwenden:
Dies gibt Ihnen natürlich auch den "anderen Standardwert", wenn der erste Wert vorhanden ist, aber eine Nullreferenz ist ...
quelle
int
. Ich bevorzuge die Verwendung vonDefaultIfEmpty
:src.Where(filter).DefaultIfEmpty(defaultValue).First()
. Funktioniert sowohl für den Werttyp als auch für den Referenztyp.Sie können DefaultIfEmpty gefolgt von First verwenden :
quelle
DefaultIfEmpty
- es funktioniert mit allen APIs , die eine Standard müssen angegeben werden:First()
,Last()
usw. Als Benutzer, müssen Sie sich nicht daran erinnern , welche APIs ermöglichen angeben Standard die dies nicht tun. Sehr elegant!Aus der Dokumentation zu FirstOrDefault
Aus der Dokumentation für Standard (T) :
Daher kann der Standardwert null oder 0 sein, je nachdem, ob der Typ ein Referenz- oder ein Werttyp ist. Sie können das Standardverhalten jedoch nicht steuern.
quelle
Aus dem Kommentar von @sloth übernommen
Stattdessen
YourCollection.FirstOrDefault()
könnten SieYourCollection.DefaultIfEmpty(YourDefault).First()
zum Beispiel verwenden.Beispiel:
quelle
DefaultIfEmpty
der Standardwert zurückgegeben wird, wenn die Sammlung leer ist (0 Elemente enthält). Wenn SieFirst
WITH mit einem übereinstimmenden Ausdruck wie in Ihrem Beispiel verwenden und diese Bedingung kein Element findet, ist Ihr Rückgabewert leer.Sie können dies auch tun
Dies verwendet nur linq - yipee!
quelle
FirstOrDefault
anstelle von verwendet wirdFirst
. Laut msdn.microsoft.com/en-us/library/bb340482.aspx ist die empfohlene VerwendungFirst
Eigentlich verwende ich zwei Ansätze, um zu vermeiden,
NullReferenceException
wenn ich mit Sammlungen arbeite:Für C # 6.0 oder höher:
Verwenden Sie
?.
oder?[
, um zu testen, ob null ist, bevor Sie einen Mitgliederzugriff durchführen. Dokumentation zu nullbedingten OperatorenBeispiel:
var barCSharp6 = list.FirstOrDefault()?.Bar;
C # ältere Version:
Verwenden Sie
DefaultIfEmpty()
diese Option , um einen Standardwert abzurufen, wenn die Sequenz leer ist. MSDN-DokumentationBeispiel:
string barCSharp5 = list.DefaultIfEmpty(new Foo()).FirstOrDefault().Bar;
quelle
Stattdessen
YourCollection.FirstOrDefault()
könnten SieYourCollection.DefaultIfEmpty(YourDefault).First()
zum Beispiel verwenden.quelle
Ich hatte gerade eine ähnliche Situation und suchte nach einer Lösung, mit der ich einen alternativen Standardwert zurückgeben kann, ohne mich jedes Mal auf der Anruferseite darum zu kümmern, wenn ich ihn benötige. Was wir normalerweise tun, falls Linq nicht unterstützt, was wir wollen, ist eine neue Erweiterung zu schreiben, die sich darum kümmert. Das ist, was ich tat. Folgendes habe ich mir ausgedacht (allerdings nicht getestet):
quelle
Ich weiß, dass es eine Weile her ist, aber ich werde es ergänzen, basierend auf der beliebtesten Antwort, aber mit einer kleinen Erweiterung möchte ich Folgendes teilen:
Dies ermöglicht es mir, es als solches mit meinem eigenen Beispiel zu bezeichnen, mit dem ich Probleme hatte:
Für mich wollte ich nur, dass ein Standard-Resolver inline verwendet wird. Ich kann meine übliche Prüfung durchführen und dann eine Funktion übergeben, damit eine Klasse nicht instanziiert wird, auch wenn sie nicht verwendet wird. Stattdessen kann sie bei Bedarf ausgeführt werden.
quelle
Verwenden Sie
DefaultIfEmpty()
anstelle vonFirstOrDefault()
.quelle