Was ist die entgegengesetzte Methode von Any <T>

80

Wie kann ich mit Linq prüfen, ob eine Sammlung kein Objekt enthält? IE Das Gegenteil von Any<T>.

Ich könnte das Ergebnis mit einem invertieren, !aber aus Gründen der Lesbarkeit habe ich mich gefragt, ob es einen besseren Weg gibt, dies zu tun. Soll ich die Erweiterung selbst hinzufügen?

Caspar Kleijne
quelle
Dann besser lesbar !? Contains, Exists?
Tigran
3
Ja, das gibt es nicht None<T>. Ich benutze oft solche benutzerdefinierten Erweiterungen für die Lesbarkeit (zum Beispiel mag ich die !dictionary.ContainsKey(key)Syntax nicht, also habe ich dictionary.NoKey(key)stattdessen implementiert .
Konrad Morawski
2
@ Morawski: Ich habe angefangen zu verwenden ConcurrentDictionary, weil es die wirklich praktische GetOrAddMethode ist, auch wenn ich keine Parallelität benötige.
Roger Lipscombe

Antworten:

87

Sie können ganz einfach eine NoneErweiterungsmethode erstellen :

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);
}
Thomas Levesque
quelle
1
Ich denke, dies wäre eine schöne Ergänzung zu Standard Linq.
Ivan
2
@ Ivan, es ist nicht in Linq selbst, aber es ist Teil meiner Linq.Extras- Bibliothek
Thomas Levesque
60

Das Gegenteil der Überprüfung, ob ein (mindestens ein) Datensatz einem bestimmten Kriterium entspricht, besteht darin, zu überprüfen, ob nicht alle Datensätze den Kriterien entsprechen.

Sie haben Ihr vollständiges Beispiel nicht veröffentlicht, aber wenn Sie das Gegenteil von etwas wie:

var isJohnFound = MyRecords.Any(x => x.FirstName == "John");

Du könntest benutzen:

var isJohnNotFound = MyRecords.All(x => x.FirstName != "John");
vivat Fische
quelle
Ich bin heute auf Google darauf gestoßen, und obwohl ich Ihrem Ansatz zustimme, verwende ich normalerweisevar isJohnNotFound = !MyRecords.All(x => x.FirstName == "John");
Chris
Natürlich habe ich vermasselt. Wenn ich das mache, wird kein einzelnes Feld überprüft. Normalerweise ist es eher !MyRecords.All(x => InvalidNames.Any(n => n == x.Name));so: Überprüfen Sie jeden Eintrag anhand einer Liste ungültiger Namen. Nur wenn keine Übereinstimmung vorliegt, ist das Ergebnis wahr.
Chris
2

Wenn Sie die Any()Methode nicht umbrechen möchten, können Sie zusätzlich zu den hinzugefügten Antworten None()Folgendes implementieren :

public static bool None<TSource>(this IEnumerable<TSource> source) 
{
    if (source == null) { throw new ArgumentNullException(nameof(source)); }

    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        return !enumerator.MoveNext();
    }
}

public static bool None<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
    if (source == null) { throw new ArgumentNullException(nameof(source)); }
    if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); }

    foreach (TSource item in source)
    {
        if (predicate(item))
        {
            return false;
        }
    }

    return true;
}

Zusätzlich können Sie für die parameterlose Überladung eine ICollection<T>Optimierung anwenden , die in der LINQ-Implementierung tatsächlich nicht vorhanden ist.

ICollection<TSource> collection = source as ICollection<TSource>;
if (collection != null) { return collection.Count == 0; }
Saro Taşciyan
quelle
2

Ich habe diesen Thread gefunden, als ich herausfinden wollte, ob eine Sammlung kein Objekt enthält, aber nicht überprüfen möchte, ob alle Objekte in einer Sammlung den angegebenen Kriterien entsprechen. Am Ende habe ich so einen Scheck gemacht:

var exists = modifiedCustomers.Any(x => x.Key == item.Key);

if (!exists)
{
    continue;
}
Ogglas
quelle