Angenommen, ich habe einige Zeichenfolgen:
%Vor%Was ist der Unterschied zwischen:
%Vor%Und:
%Vor%Da Where () verzögert ist, sollte es die Ausführung nicht verlangsamen, oder?
Die Leistungseinbußen bei der Verwendung von .Where(filter).First()
anstatt .First(filter)
sind normalerweise sehr klein.
Sie sind jedoch nicht gleich - Where
erzeugt einen neuen Iterator, der First
einfach ein Element von nehmen kann, während First(filter)
Mikrooptimierung durch Verwendung nur einer Schleife und einer direkten Rückgabe, wenn filter
übereinstimmt .
Während also beide Ansätze die gleiche Semantik haben und beide filter
gleich oft ausführen (nur so oft wie nötig), muss First
mit einem filter
-Parameter kein intermediäres Iteratorobjekt und
Mit anderen Worten, wenn Sie millionenfach Code ausführen, sehen Sie einen leichten Leistungsunterschied - aber nichts Großes; Ich würde mich nie Sorgen machen. Wann immer dieser kleine Leistungsunterschied wirklich wichtig ist, ist es viel besser, nur die (sehr einfache) foreach-with-if-Anweisung zu schreiben, die äquivalent ist und die zusätzlichen LINQ-Aufrufe und -Objektzuweisungen vermeidet - aber denken Sie daran, dass dies eine Mikrooptimierung ist selten brauchen.
Bearbeiten: Benchmark, der den Effekt demonstriert:
Das dauert 0,78 Sekunden:
%Vor%Aber das dauert 1,41 Sekunden:
%Vor%Während einfache Schleifen viel schneller sind (0,13 Sekunden):
%Vor%Beachten Sie, dass dieser Benchmark nur so extreme Unterschiede zeigt, weil ich einen trivialen Filter und ein sehr kurzes nicht übereinstimmendes Präfix habe.
Aufgrund einiger schneller Experimente scheint der Unterschied größtenteils auf die Details zurückzuführen zu sein, aus denen Codepath genommen wird. Also, für Array's und List<>
s ist die erste Variante tatsächlich schneller, wahrscheinlich eine spezielle Hülle in .Where
für die Typen, die First
nicht hat; Für benutzerdefinierte Iteratoren ist die zweite Version erwartungsgemäß ein kleines bisschen schneller.
.Where(...).First()
ist ungefähr so schnell wie .First(...)
- stört es nicht, das eine oder andere als Optimierung zu wählen. In general .First(...)
ist sehr wenig schneller, aber in einigen häufigen Fällen ist es langsamer. Wenn Sie diese Mikrooptimierung wirklich benötigen, verwenden Sie einfache Schleifen, die schneller sind als beide.
Hier gibt es keine Unterschiede.
Calling Wobei zuerst ein Iterator zurückgegeben wird, der nicht verwendet wird, bis First mit dem Schleifen beginnt.
Wenn das Prädikat mit keinem Element übereinstimmt, wird dieselbe Ausnahme InvalidOperationException ausgelöst.
Der einzige Unterschied ist die Ausführlichkeit des Codes, also .Front ohne. Wo sollte bevorzugt werden
Im speziellen Fall, wenn First
und Where
für string[]
aufgerufen werden, sind die aufgerufenen Methoden die Erweiterungsmethoden Enumerable.Where
und Enumerable.First
.
Enumerable.Where
macht das:
und der Konstruktor von WhereArrayIterator
macht nur:
Es wird also nichts getan, außer einen Iterator zu erstellen.
Die erste First
Methode ohne Prädikat tut das:
Das zweite First
macht dies jedoch
Was bei einem Array so schnell ist wie direkter linearer Zugriff.
Zusammenfassend bedeutet dies, dass das Aufrufen von First(predicate)
auf einem Array etwas schneller ist, durch einen nicht großen, aber dennoch erkennbaren Faktor. Dies gilt möglicherweise nicht für Listen und wird sicherlich nicht für IQueryable
Objekte gelten, die eine völlig andere Geschichte sind.
Dies ist jedoch die Mikrooptimierung im schlimmsten Fall. Wenn dies nicht millionenfach geschieht, spart es nicht zu viele Sekunden. Selbst wenn ich das jetzt weiß, werde ich immer noch das verwenden, was klarer zu lesen und zu verstehen ist.