Wann wird .First und wann .FirstOrDefault mit LINQ verwendet?

824

Ich habe mich umgesehen und keine klare Antwort gefunden, wann Sie es verwenden möchten .Firstund wann Sie es .FirstOrDefaultmit LINQ verwenden möchten .

  • Wann möchten Sie verwenden .First? Nur wenn Sie die Ausnahme abfangen möchten, wenn keine Ergebnisse zurückgegeben wurden?

    var result = List.Where(x => x == "foo").First();
  • Und wann möchten Sie verwenden .FirstOrDefault? Wann möchten Sie immer den Standardtyp, wenn kein Ergebnis?

    var result = List.Where(x => x == "foo").FirstOrDefault();
  • Und was ist mit Take?

    var result = List.Where(x => x == "foo").Take(1);
Metro Schlumpf
quelle
86
.Firstund .FirstOrDefaultbeide nehmen Prädikate als Argumente, var result = List.Where(x => x == "foo").First();könnten also umgeschrieben werden alsvar result = List.First(x => x == "foo");
Rian Schmits
59
Vergessen Sie nicht , zu prüfen Singleund SingleOrDefault. Ich hasse es, wenn Leute benutzen, Firstwenn sie es wirklich meinen Single; )
BartoszKP
19
Single oder SingleOrDefault würden eine Ausnahme auslösen, wenn mehr als ein Element zurückgegeben wird! Ich denke, FirstOrDefault ist in den meisten Fällen besser!
Eric Draven
21
Der Punkt ist, wenn Sie ein einzelnes Ergebnis erwarten, sollten Sie dies sagen, und die Ausnahme zeigt an, dass Ihre Logik fehlgeschlagen ist.
NetMage
1
Bedenken Sie auch, dass die Verwendung .FirstOrDefault()immer die Möglichkeit bietet, eine aussagekräftigere Ausnahme auszulösen. Wenn eine Sequenzausnahme ausgelöst wird und mehrere .First()in einer Methode enthalten sind, kann es schwierig sein, zu erkennen, welche Anweisung das Problem ist.
StingyJack

Antworten:

807

Ich würde verwenden, First()wenn ich weiß oder erwarte, dass die Sequenz mindestens ein Element enthält. Mit anderen Worten, wenn es ein außergewöhnliches Ereignis ist, dass die Sequenz leer ist.

Verwenden FirstOrDefault()Sie diese Option, wenn Sie wissen, dass Sie überprüfen müssen, ob ein Element vorhanden ist oder nicht. Mit anderen Worten, wenn es legal ist, dass die Sequenz leer ist. Sie sollten sich bei der Prüfung nicht auf die Ausnahmebehandlung verlassen. (Es ist eine schlechte Übung und kann die Leistung beeinträchtigen).

Schließlich besteht der Unterschied zwischen First()und Take(1)darin, dass First()das Element selbst zurückgegeben wird, während Take(1)eine Folge von Elementen zurückgegeben wird, die genau ein Element enthält.

driis
quelle
4
@driis - Ich würde mir vorstellen, dass wir das Mantra der Ausnahmerichtlinie für außergewöhnliche Ausnahmen verwenden können, wenn wir zwischen First und FirstOrDefault wählen. Danke für die klare Antwort.
Metro Schlumpf
5
Das einzige, was ich hinzufügen möchte, ist, dass, wenn der Standardwert für den ausgewählten Typ ein gültiger Wert sein könnte, beispielsweise Ihr Ergebnis der int-Wert 0, die Behandlung der Ausnahme der beste Weg ist, dies zu behandeln .
PeterBelm
25
Scratch that, ich habe einen viel schöneren Weg gefunden, dies zu erreichen. Verwenden Sie: DefaultIfEmpty (-1) .First ()
PeterBelm
5
Take gibt nicht genau ein Element zurück, sondern höchstens ein Element (wenn Sie 1 angeben, natürlich). Es kann genauso gut 0 Elemente zurückgeben, wenn die Sequenz anfänglich leer ist.
SPIRiT_1984
3
@ RoyiNamir, ja im Zusammenhang mit der Frage, wo der zu verwendende Parameter 1 ist. Ich habe auch festgestellt, dass in parens unmittelbar nach diesem Satz.
Driis
272

.Firstlöst eine Ausnahme aus, wenn keine Ergebnisse vorliegen. .FirstOrDefaultwird nicht, es wird einfach entweder null (Referenztypen) oder der Standardwert des Werttyps zurückgegeben. (zB wie 0für ein int.) Die Frage hier ist nicht, wann Sie den Standardtyp wollen, sondern mehr: Sind Sie bereit, eine Ausnahme oder einen Standardwert zu behandeln? Da Ausnahmen außergewöhnlich sein sollten, FirstOrDefaultwird sie bevorzugt, wenn Sie nicht sicher sind, ob Sie Ergebnisse aus Ihrer Abfrage erhalten. Wenn die Daten logisch vorhanden sein sollten, kann die Ausnahmebehandlung in Betracht gezogen werden.

Skip()und Take()werden normalerweise beim Einrichten von Paging in Ergebnissen verwendet. (Wie das Anzeigen der ersten 10 Ergebnisse und der nächsten 10 auf der nächsten Seite usw.)

Hoffe das hilft.

Jeroen Landheer
quelle
5
@Jeroen - guter Punkt für bessere Anwendungsfälle für die Verwendung von Skip / Take.
Metro Schlumpf
4
+1 für eine Erklärung, .FirstOrDefaultdie für Referenztypen null zurückgibt. Ich war verwirrt darüber, was ein "Standard" -Objekt sein würde. Diese Antwort hat das geklärt.
Mike Taverne
115

.First()löst eine Ausnahme aus, wenn keine Zeile zurückgegeben werden soll, und .FirstOrDefault()gibt NULLstattdessen den Standardwert ( für alle Referenztypen) zurück.

Wenn Sie also bereit und bereit sind, eine mögliche Ausnahme zu behandeln, .First()ist dies in Ordnung. Wenn Sie den Rückgabewert != nulltrotzdem überprüfen möchten , .FirstOrDefault()ist dies die bessere Wahl.

Aber ich denke, es ist auch eine persönliche Präferenz. Verwenden Sie, was für Sie sinnvoller ist und besser zu Ihrem Codierungsstil passt.

marc_s
quelle
66

Zuerst()

  1. Gibt das erste Element einer Sequenz zurück.
  2. Es wird ein Fehler ausgegeben, wenn das Ergebnis kein Element enthält oder die Quelle null ist.
  3. Sie sollten es verwenden, wenn mehr als ein Element erwartet wird und Sie nur das erste Element möchten.

FirstOrDefault ()

  1. Gibt das erste Element einer Sequenz oder einen Standardwert zurück, wenn kein Element gefunden wird.
  2. Es wird nur dann ein Fehler ausgegeben, wenn die Quelle null ist.
  3. Sie sollten es verwenden, wenn mehr als ein Element erwartet wird und Sie nur das erste Element möchten. Auch gut, wenn das Ergebnis leer ist.

Wir haben eine UserInfos-Tabelle, die einige Datensätze enthält, wie unten gezeigt. Auf der Grundlage dieser Tabelle unten habe ich ein Beispiel erstellt ...

UserInfo-Tabelle

Verwendung von First ()

var result = dc.UserInfos.First(x => x.ID == 1);

Es gibt nur einen Datensatz, in dem ID == 1. Sollte diese Datensatz-
ID zurückgeben: 1 Vorname: Manish Nachname: Dubey E-Mail: [email protected]

var result = dc.UserInfos.First(x => x.FName == "Rahul");   

Es gibt mehrere Datensätze, in denen FName == "Rahul". Die erste Aufzeichnung sollte zurückgegeben werden.
ID: 7 Vorname: Rahul Nachname: Sharma E-Mail: [email protected]

var result = dc.UserInfos.First(x => x.ID ==13);

Es gibt keinen Datensatz mit der ID == 13. Es sollte ein Fehler auftreten.
InvalidOperationException: Die Sequenz enthält keine Elemente

Verwendung von FirstOrDefault ()

var result = dc.UserInfos.FirstOrDefault(x => x.ID == 1);

Es gibt nur einen Datensatz, in dem ID == 1. Sollte diese Datensatz-
ID zurückgeben: 1 Vorname: Manish Nachname: Dubey E-Mail: [email protected]

var result = dc.UserInfos.FirstOrDefault(x => x.FName == "Rahul");

Es gibt mehrere Datensätze, in denen FName == "Rahul". Die erste Aufzeichnung sollte zurückgegeben werden.
ID: 7 Vorname: Rahul Nachname: Sharma E-Mail: [email protected]

var result = dc.UserInfos.FirstOrDefault(x => x.ID ==13);

Es gibt keinen Datensatz mit der ID == 13. Der Rückgabewert ist null

Hoffe, es wird Ihnen helfen zu verstehen, wann First()oder verwenden FirstOrDefault().

Mukesh Kumar
quelle
4
Meiner Meinung nach sollte die Aussage "Ein Fehler sollte auftreten." unter dem dritten FirstOrDefault () - Beispiel ist irreführend.
Jannik
Hallo, Sie erklären es gut, aber ich bin ein wenig verwirrt, wann Daten vom Join abgerufen werden und wann zu diesem Zeitpunkt keine ID in einer Fremdschlüsseltabelle vorhanden war. Welche wird verwendet? Derzeit verwende ich First (), aber nachdem ich Ihre Antwort gelesen habe, habe ich keine Ahnung. Bitte helfen Sie
Brijesh Mavani
20

Zunächst einmal Takeist eine ganz andere Methode. Es gibt eine IEnumerable<T>und keine einzige zurück T, also ist das raus.

Zwischen Firstund FirstOrDefaultsollten Sie verwenden, Firstwenn Sie sicher sind, dass ein Element vorhanden ist, und wenn dies nicht der Fall ist, liegt ein Fehler vor.

Übrigens, wenn Ihre Sequenz default(T)Elemente enthält (z. B. null) und Sie zwischen leer und dem ersten Element unterscheiden müssen, nullkönnen Sie nicht verwenden FirstOrDefault.

Mehrdad Afshari
quelle
2
@Mehrdad - tolle Punkte, re: .First gibt IEnumerable zurück und wenn FirstOrDefault nicht verwendet werden soll.
Metro Schlumpf
15

Zuerst:

  • Gibt das erste Element einer Sequenz zurück
  • Löst eine Ausnahme aus: Das Ergebnis enthält keine Elemente
  • Verwendung wann: Wenn mehr als 1 Element erwartet wird und Sie nur das erste möchten

FirstOrDefault:

  • Gibt das erste Element einer Sequenz oder einen Standardwert zurück, wenn kein Element gefunden wird
  • Löst eine Ausnahme aus: Nur wenn die Quelle null ist
  • Verwendung wann: Wenn mehr als 1 Element erwartet wird und Sie nur das erste möchten. Es ist auch in Ordnung, wenn das Ergebnis leer ist

Von: http://www.technicaloverload.com/linq-single-vs-singleordefault-vs-first-vs-firstordefault/

user2051770
quelle
10

Ein weiterer zu beachtender Unterschied besteht darin, dass Sie beim Debuggen einer Anwendung in einer Produktionsumgebung möglicherweise keinen Zugriff auf Zeilennummern haben. Daher .First()kann es schwierig sein , festzustellen, welche bestimmte Anweisung in einer Methode die Ausnahme ausgelöst hat.

Die Ausnahmemeldung enthält auch keine Lambda-Ausdrücke, die Sie möglicherweise verwendet haben, wodurch Probleme noch schwieriger zu debuggen sind.

Deshalb benutze ich immer FirstOrDefault(), obwohl ich weiß, dass ein Null-Eintrag eine Ausnahmesituation darstellen würde.

var customer = context.Customers.FirstOrDefault(i => i.Id == customerId);
if (customer == null)
{
   throw new Exception(string.Format("Can't find customer {0}.", customerId));
}
Kye
quelle
5

Zuerst()

Wenn Sie wissen, dass das Ergebnis mehr als 1 erwartetes Element enthält, sollten Sie nur das erste Element der Sequenz verwenden.

FirstOrDefault ()

FirstOrDefault () ist genau wie First (), außer dass, wenn kein Element der angegebenen Bedingung entspricht, der Standardwert des zugrunde liegenden Typs der generischen Sammlung zurückgegeben wird. Es wird keine InvalidOperationException ausgelöst, wenn kein Element gefunden wurde. Die Sammlung von Elementen oder Sequenzen ist jedoch null, als sie eine Ausnahme auslöst.

Nimesh Khatri
quelle
Hallo, Sie erklären es gut, aber ich bin ein wenig verwirrt, wann Daten vom Join abgerufen werden und wann zu diesem Zeitpunkt keine ID in einer Fremdschlüsseltabelle vorhanden war. Welche wird verwendet? Derzeit verwende ich First (), aber nachdem ich Ihre Antwort gelesen habe, habe ich keine Ahnung. Bitte helfen Sie
Brijesh Mavani
4

Dieser Funktionstyp gehört zu Elementoperatoren. Einige nützliche Elementoperatoren sind unten definiert.

  1. First / FirstOrDefault
  2. Last / LastOrDefault
  3. Single / SingleOrDefault

Wir verwenden Elementoperatoren, wenn wir ein einzelnes Element aus einer Sequenz basierend auf einer bestimmten Bedingung auswählen müssen. Hier ist ein Beispiel.

  List<int> items = new List<int>() { 8, 5, 2, 4, 2, 6, 9, 2, 10 };

Der Operator First () gibt das erste Element einer Sequenz zurück, nachdem die Bedingung erfüllt wurde. Wenn kein Element gefunden wird, wird eine Ausnahme ausgelöst.

int result = items.Where (item => item == 2) .First ();

Der Operator FirstOrDefault () gibt das erste Element einer Sequenz zurück, nachdem die Bedingung erfüllt wurde. Wenn kein Element gefunden wird, wird der Standardwert dieses Typs zurückgegeben.

int result1 = items.Where (item => item == 2) .FirstOrDefault ();

Sheo Dayal Singh
quelle
schön erklärt mit einem leicht verständlichen Beispiel.
Arslan Bhatti
3

Ich habe eine Website, die die Notwendigkeit für FirstOrDefault zu erklären apperars
http://thepursuitofalife.com/the-linq-firstordefault-method-and-null-resultsets/
Wenn es keine Ergebnisse einer Abfrage sind, und Sie wollen zunächst anrufen () oder Single (), um eine einzelne Zeile zu erhalten ... Sie erhalten die Ausnahme "Sequenz enthält keine Elemente".

Haftungsausschluss: Ich habe LINQ noch nie verwendet. Ich entschuldige mich, wenn dies nicht der Fall ist.

NULL
quelle
2
someList.First(); // exception if collection is empty.
someList.FirstOrDefault(); // first item or default(Type)

Welches verwenden? Dies sollte von der Geschäftslogik entschieden werden und nicht von der Angst vor Ausnahmen / Programmfehlern.

Zum Beispiel, wenn die Geschäftslogik besagt, dass wir an keinem Arbeitstag keine Transaktionen durchführen können (nehmen Sie einfach an). Dann sollten Sie nicht versuchen, dieses Szenario mit einer intelligenten Programmierung zu behandeln. Ich werde immer First () für eine solche Sammlung verwenden und das Programm fehlschlagen lassen, wenn etwas anderes die Geschäftslogik durcheinander gebracht hat.

Code:

var transactionsOnWorkingDay = GetTransactionOnLatestWorkingDay();
var justNeedOneToProcess = transactionsOnWorkingDay.First(): //Not FirstOrDefault()

Ich würde gerne andere Kommentare dazu sehen.

Manish Basantani
quelle
Der Standardwert für Referenztypen und nullfähige Typen ist null.
dsa
Ein schneller Fehler ist gut - für das von Ihnen beschriebene Szenario würde ich jedoch lieber zuerst sehen, ob er fehlschlägt, die Ausnahme abfängt und dann einen aussagekräftigen Fehler zurückgibt. Like catch (InvalidOperationException e) {neue InvalidOperationException auslösen ("Kann an einem Tag keine Nulltransaktionen haben!", E)}; Aber ja, es ist sehr schlecht, die Standardeinstellung zu verwenden, um zu vermeiden, dass ein echtes Problem mit der Geschäftslogik gelöst wird.
Mathieson
1

Ok, lass mich meine zwei Cent geben. First / Firstordefault sind für die Verwendung des zweiten Konstruktors vorgesehen. Ich werde nicht erklären, was es ist, aber es ist, wenn Sie möglicherweise immer eine verwenden würden, weil Sie keine Ausnahme verursachen möchten.

person = tmp.FirstOrDefault(new Func<Person, bool>((p) =>
{
    return string.IsNullOrEmpty(p.Relationship);
}));
Arian
quelle
Nicht genau. Der erste Konstruktor wird häufig verwendet, wenn Sie nur ein Element abrufen müssen oder einen Kompilierungsfehler vermeiden müssen, wenn Sie das Ergebnis einem Wert zuweisen, der kein Array ist, und Sie sicher sind, dass die Abfrage genau ein Ergebnis zurückgibt. Während es möglicherweise schneller aussieht, den zweiten Konstruktor zu verwenden, als einen zusätzlichen .Where () zu verwenden (weil Sie glauben, dass LINQ die Auswertung von Elementen in der Liste nach dem Finden des ersten beendet), stoppt es immer beim ersten Element
usr-local-ΕΨΗΕΛΩΝ
0

Andere haben den Unterschied zwischen First()und sehr gut beschrieben FirstOrDefault(). Ich möchte einen weiteren Schritt zur Interpretation der Semantik dieser Methoden machen. Meiner Meinung nach FirstOrDefaultwird viel überbeansprucht. In den meisten Fällen erwarten Sie beim Filtern von Daten entweder eine Sammlung von Elementen, die der logischen Bedingung entsprechen, oder ein einzelnes eindeutiges Element anhand seiner eindeutigen Kennung - wie z. B. ein Benutzer, ein Buch, ein Beitrag usw. warum wir sogar so weit kommen können zu sagen, dass dies FirstOrDefault()ein Codegeruch ist, nicht weil etwas nicht stimmt, sondern weil es viel zu oft verwendet wird. Dieser Blog-Beitrag befasst sich ausführlich mit dem Thema. IMO meistensSingleOrDefault() ist eine viel bessere Alternative. Achten Sie also auf diesen Fehler und stellen Sie sicher, dass Sie die am besten geeignete Methode verwenden, die Ihren Vertrag und Ihre Erwartungen klar darstellt.

Vasil Kosturski
quelle
-6

Es gibt viele Möglichkeiten, einzelne einfache Abfragen für Sammlungen zu implementieren. Wir schreiben nur Joins in SQL. Je nach Bedarf und Notwendigkeit kann zuerst oder zuletzt ein Filter angewendet werden.

Hier ist ein Beispiel, in dem wir ein Element mit einer ID in einer Sammlung finden können. Um mehr dazu hinzuzufügen FirstOrDefault, würden Methoden First idealerweise dasselbe zurückgeben, wenn eine Sammlung mindestens einen Datensatz enthält. Wenn eine Sammlung jedoch in Ordnung ist, leer zu sein. Dann Firstwird eine Ausnahme zurückgegeben, aber FirstOrDefaultzurückgegeben nulloder standardmäßig. Zum Beispiel intwird 0 zurückgegeben. Daher wird die Verwendung solcher zwar als persönliche Präferenz bezeichnet, aber es ist besser, sie zu verwenden FirstOrDefault, um die Behandlung von Ausnahmen zu vermeiden. Hier ist ein Beispiel, in dem wir eine Sammlung von Transaktionslisten durchlaufen

venkat
quelle