Ich verstehe, dass das etwas trivial ist, aber ...
Was ist der beste Weg, um die Referenz als erstes Element einer Sammlung zu erhalten? Angenommen, die Sammlung enthält Elemente eines Referenztyps.
Codebeispiel 1:
%Vor%Das obige Beispiel hat zwei separate Aufrufe für die Sammlung, die eine Iteration starten, die abgeschlossen wird, sobald die erste erkannt wird.
Codebeispiel 2:
%Vor%Das obige Beispiel hat nur einen einzigen Aufruf für die Sammlung, führt aber eine Variable ein, die unnötigerweise in einem weiteren Bereich liegt.
Gibt es Best Practices für dieses Szenario? Gibt es eine bessere Lösung?
Ich bevorzuge das zweite Beispiel, weil es im allgemeinen effizienter ist. Es ist möglich, dass diese Sammlung eine Kombination aus vielen verschiedenen verzögerten LINQ-Abfragen ist, so dass selbst das erste Element eine nicht unerhebliche Menge an Arbeit erfordert.
Stellen Sie sich zum Beispiel vor, dass diese Sammlung aus der folgenden LINQ-Abfrage erstellt wird
%Vor% Um nur das erste Element von collection
zu erhalten, ist eine vollständige Sortierung des Inhalts von originalList
erforderlich. Diese vollständige Sortierung erfolgt jedes Mal, wenn die Elemente von collection
ausgewertet werden.
Die erste Stichprobe bewirkt, dass die potenziell teure Sammlung zweimal ausgewertet wird: über die Methode Any
und First
. Das zweite Beispiel wertet die Sammlung nur einmal aus, und daher würde ich es über das erste auswählen.
Die zweite Funktion arbeitet nicht mit nicht nullbaren Wertetypen ( Bearbeiten: wie Sie angenommen haben - das erste Mal nicht) und hat außer der ersten, die eine a hat, keine Alternative Rennzustand. Es gibt zwei Alternativen, die beide geeignet sind - die Auswahl des einen oder anderen hängt davon ab, wie oft Sie eine leere Sequenz erhalten.
Wenn es sich um einen häufigen oder erwarteten Fall handelt, bei dem Sie eine leere Enumeration erhalten, ist die Verwendung einer foreach
-Schleife relativ ordentlich:
oder wenn du% break
nicht drin haben willst (was verständlich ist):
Wenn es relativ ungewöhnlich ist, dass es leer ist, dann sollte ein try/catch
-Block die beste Leistung bringen (da Ausnahmen nur dann teuer sind, wenn sie tatsächlich ausgelöst werden - eine nicht erhobene Ausnahme ist praktisch frei):
Eine dritte Option besteht darin, einen Enumerator direkt zu verwenden, obwohl dieser identisch mit der foreach
-Version sein sollte und etwas weniger klar ist:
Oder als Erweiterung der Lösung von Gabe, verwenden Sie ein Lambda, damit Sie das if:
fallen lassen können %Vor%Und benutze es wie:
%Vor% Da alle generischen Collections
(dh: vom Typ System. Collections.ObjectModel ) habe das Count
-Member wie folgt:
Dies ist sicher, da alle Collections sowohl die Count
als auch die Item
Eigenschaft besitzen. Es ist auch sehr geradlinig und leicht für andere Programmierer, die Ihren Code lesen, um zu verstehen, was Ihre Absicht ist.
Sie haben einfach einen einfachen Test für den primitiven Typ durchgeführt und sehen so aus, als ob Ihr Codebeispiel # 2 in diesem Fall am schnellsten ist (aktualisiert):
%Vor% AnyFirst
NonEmpty: 00: 00: 00.0000262 Sekunden
EmptySet: 00: 00: 00.0000174 Sekunden
ForLoop
NonEmpty: 00: 00: 00.0000158 Sekunden
EmptySet: 00: 00: 00.0000151 Sekunden
NullCheck
NonEmpty: 00: 00: 00.0000088 Sekunden
EmptySet: 00: 00: 00.0000064 Sekunden
TryGetFirst
NonEmpty: 00: 00: 00.0000177 Sekunden
EmptySet: 00: 00: 00.0000172 Sekunden