Oft möchte ich überprüfen, ob ein angegebener Wert mit einem in einer Liste übereinstimmt (z. B. bei der Validierung):
if (!acceptedValues.Any(v => v == someValue))
{
// exception logic
}
Kürzlich habe ich festgestellt, dass ReSharper mich gebeten hat, diese Abfragen zu vereinfachen, um:
if (acceptedValues.All(v => v != someValue))
{
// exception logic
}
Offensichtlich ist dies logisch identisch, vielleicht etwas besser lesbar (wenn Sie viel Mathematik gemacht haben). Meine Frage lautet: Führt dies zu einem Leistungseinbruch?
Es fühlt sich so an, wie es sollte (dh es .Any()
klingt so, als würde es kurzschließen, während es so .All()
klingt, als ob es nicht so wäre), aber ich habe nichts, um dies zu begründen. Hat jemand ein tieferes Wissen darüber, ob die Abfragen dasselbe lösen oder ob ReSharper mich in die Irre führt?
if (!sequence.Any(v => v == true))
. Wenn Sie nur fortfahren möchten, wenn alles einer bestimmten Spezifikation entspricht :if (sequence.All(v => v < 10))
.Antworten:
Implementierung von
All
gemäß ILSpy (wie in Ich habe tatsächlich nachgesehen und nicht nach "Nun, diese Methode funktioniert ein bisschen wie ...", was ich tun könnte, wenn wir eher die Theorie als die Auswirkungen diskutieren würden).Implementierung von
Any
nach ILSpy:Natürlich könnte es einen subtilen Unterschied in der produzierten IL geben. Aber nein, nein gibt es nicht. Die IL ist ziemlich gleich, aber für die offensichtliche Umkehrung der Rückgabe von true bei Prädikatübereinstimmung gegenüber der Rückgabe von false bei Prädikatfehlanpassung.
Dies ist natürlich nur Linq-for-Objects. Es ist möglich, dass ein anderer Linq-Anbieter einen viel besser behandelt als den anderen, aber wenn dies der Fall ist, ist es ziemlich zufällig, welcher die optimalere Implementierung erhalten hat.
Es scheint, dass die Regel nur auf jemanden zurückzuführen ist, der das Gefühl hat,
if(determineSomethingTrue)
einfacher und lesbarer zu sein alsif(!determineSomethingFalse)
. Und fairerweise denke ich, dass sie einen gewissen Punkt haben, den ich oftif(!someTest)
verwirrend finde *, wenn es einen alternativen Test von gleicher Ausführlichkeit und Komplexität gibt, der für die Bedingung, auf die wir reagieren wollen, wahr ist. Ich persönlich finde jedoch nichts, was eine der beiden von Ihnen angegebenen Alternativen gegenüber der anderen bevorzugt, und würde mich vielleicht ganz leicht zu der ersteren neigen, wenn das Prädikat komplizierter wäre.* Nicht verwirrend wie in Ich verstehe nicht, aber verwirrend wie in Ich mache mir Sorgen, dass es einen subtilen Grund für die Entscheidung gibt, den ich nicht verstehe, und es braucht ein paar mentale Sprünge, um zu erkennen, dass "Nein, sie haben sich einfach dazu entschlossen Warten Sie auf diese Weise, worauf habe ich diesen Code noch einmal angeschaut? ... "
quelle
Any
wird zurückkehrenfalse
und daher!Any
zurückkehrentrue
, so dass sie identisch sind.!test.Any(x => x.Key == 3 && x.Value == 1)
diesen VerwendungenAll
isttest.All(x => !(x.Key == 3 && x.Value == 1))
(was in der Tat äquivalent zu isttest.All(x => x.Key != 3 || x.Value != 1)
).Diese Erweiterungsmethoden machen Ihren Code möglicherweise besser lesbar:
Jetzt anstelle Ihres Originals
du könntest sagen
quelle
Beide haben die gleiche Leistung, da beide die Aufzählung beenden, nachdem das Ergebnis bestimmt werden kann -
Any()
beim ersten Element wird das übergebene Prädikat ausgewertettrue
undAll()
beim ersten Element wird das Prädikat ausgewertetfalse
.quelle
All
Kurzschlüsse bei der ersten Nichtübereinstimmung, daher ist dies kein Problem.Ein Bereich der Subtilität ist das
Ist wahr. Alle Elemente in der Sequenz sind gerade.
Weitere Informationen zu dieser Methode finden Sie in der Dokumentation zu Enumerable.All .
quelle
bool allEven = !Enumerable.Empty<int>().Any(i => i % 2 != 0)
das stimmt auch.All()
bestimmt, ob alle Elemente einer Sequenz eine Bedingung erfüllen.Any()
bestimmt, ob ein Element einer Sequenz die Bedingung erfüllt.quelle
Nach diesem Link
quelle
Wie andere Antworten bereits ausführlich dargelegt haben: Hier geht es nicht um Leistung, sondern um Klarheit.
Es gibt breite Unterstützung für beide Optionen:
Aber ich denke, dies könnte eine breitere Unterstützung erreichen :
Einfach den Booleschen Wert zu berechnen (und ihn zu benennen), bevor etwas negiert wird, macht dies in meinem Kopf sehr deutlich.
quelle
Wenn Sie sich die Enumerable-Quelle ansehen, werden Sie feststellen, dass die Implementierung von
Any
undAll
ziemlich nah ist:Es gibt keine Möglichkeit, dass eine Methode wesentlich schneller als die andere ist, da der einzige Unterschied in einer booleschen Negation liegt. Ziehen Sie daher die Lesbarkeit dem falschen Leistungsgewinn vor.
quelle