wake-up-neo.com

LINQ: Nicht alle gegen alle nicht

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 ist mir aufgefallen, 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 mathematisch gearbeitet haben). Meine Frage lautet: Führt dies zu einem Leistungseinbruch?

Es fühlt sich an wie es sollte (d. H. .Any() klingt wie es kurzschließt, wohingegen .All() so klingt wie es nicht klingt), aber ich habe nichts, um dies zu begründen. Hat jemand tiefere Kenntnisse darüber, ob die Fragen gleich gelöst werden oder ob ReSharper mich in die Irre führt?

257
Mark

Diese Erweiterungsmethoden verbessern möglicherweise die Lesbarkeit Ihres Codes:

public static bool None<TSource>(this IEnumerable<TSource> source)
{
    return !source.Any();
}

public static bool None<TSource>(this IEnumerable<TSource> source, 
                                 Func<TSource, bool> predicate)
{
    return !source.Any(predicate);
}

Jetzt anstelle Ihres Originals

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

du könntest sagen

if (acceptedValues.None(v => v == someValue))
{
    // exception logic
}
52
AakashM

Beide hätten die gleiche Leistung, da beide die Aufzählung stoppen, nachdem das Ergebnis bestimmt werden kann - Any() für das erste Element, das das übergebene Prädikat zu true und All() für das erste Element auswertet Das Prädikat ergibt false.

23
BrokenGlass

All Kurzschlüsse bei der ersten Nichtübereinstimmung, also kein Problem.

Ein Bereich der Subtilität ist das

 bool allEven = Enumerable.Empty<int>().All(i => i % 2 == 0); 

Ist wahr. Alle Elemente in der Sequenz sind gerade.

Weitere Informationen zu dieser Methode finden Sie in der Dokumentation zu Enumerable.All .

19
Anthony Pegram

All() bestimmt, ob alle Elemente einer Sequenz eine Bedingung erfüllen.
Any() bestimmt, ob ein Element einer Sequenz die Bedingung erfüllt.

var numbers = new[]{1,2,3};

numbers.All(n => n % 2 == 0); // returns false
numbers.Any(n => n % 2 == 0); // returns true
6
emy

Wie andere Antworten bereits ausführlich dargelegt haben: Es geht nicht um Leistung, sondern um Klarheit.

Es gibt eine breite Unterstützung für beide Optionen:

if (!acceptedValues.Any(v => v == someValue))
{
    // exception logic
}

if (acceptedValues.All(v => v != someValue))
{
    // exception logic
}

Aber ich denke dies könnte zu einer breiteren Unterstützung führen:

var isValueAccepted = acceptedValues.Any(v => v == someValue);
if (!isValueAccepted)
{
    // exception logic
}

Einfach den Booleschen Wert zu berechnen (und ihn zu benennen), bevor irgendetwas negiert wird, macht dies in meinen Gedanken deutlich.

5
Michael Haren

Demnach link

Beliebig - Prüft, ob mindestens eine Übereinstimmung vorliegt

Alle - Überprüft, ob alle übereinstimmen

5
rcarvalhoxavier

Wenn Sie sich Enumerable source ansehen, werden Sie feststellen, dass die Implementierung von Any und All ziemlich nahe ist:

public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (predicate(element)) return true;
    }
    return false;
}

public static bool All<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate) {
    if (source == null) throw Error.ArgumentNull("source");
    if (predicate == null) throw Error.ArgumentNull("predicate");
    foreach (TSource element in source) {
        if (!predicate(element)) return false;
    }
    return true;
}

Es gibt keine Möglichkeit, dass eine Methode signifikant schneller ist als die andere, da der einzige Unterschied in einer booleschen Negation liegt. Ziehen Sie daher die Lesbarkeit vor dem falschen Leistungsgewinn.

3
Thomas Ayoub