webentwicklung-frage-antwort-db.com.de

Empfohlene Methode, um zu überprüfen, ob eine Sequenz leer ist

Eine Methode gibt eine Sequenz IEnumerable<T> zurück, und Sie möchten jetzt prüfen, ob sie leer ist. Wie empfehlen Sie das? Ich suche sowohl gute Lesbarkeit als auch gute Leistung. 

Der erste und naheliegendste Weg ist, zu überprüfen, ob die Anzahl größer als Null ist:

if(sequence.Count() == 0)

Hat eine anständige Lesbarkeit, aber schreckliche Leistung, da es tatsächlich die gesamte Sequenz durchlaufen muss.

Eine Methode, die ich manchmal verwende, ist folgende:

if(!sequence.Any())

Dies muss (soweit ich weiß) nicht die gesamte Sequenz durchlaufen, aber die Lesbarkeit ist ein wenig rückwärts und umständlich. (Liest sich viel besser, wenn wir prüfen, dass die Sequenz nicht leer ist).

Eine andere Option ist die Verwendung von First in einem try-catch wie folgt:

try
{
    sequence.First();
}
catch(InvalidOperationException)
{
    // Do something
}

Keine sehr schöne Lösung und wahrscheinlich auch langsamer, da es Ausnahmen und so verwendet. Könnte dies verhindern, indem Sie natürlich FirstOrDefault verwenden, außer Sie hätten ein großes Problem, wenn das erste Element in der Sequenz tatsächlich der Standardwert war;)

Also, andere Möglichkeiten, um zu überprüfen, ob eine Sequenz leer ist? Welches benutzen Sie normalerweise? Welches empfehlen Sie zu verwenden?

Anmerkung: Für eine optimale Lesbarkeit würde ich wahrscheinlich einen der obigen Ausschnitte in eine IsEmpty-Erweiterungsmethode einfügen, aber ich bin immer noch neugierig, da ich auch etwas innerhalb dieser Methode tun müsste: p

46
Svish

Ich würde !sequence.Any() persönlich verwenden.

Wenn Sie wirklich müssen, können Sie immer Ihre eigene Erweiterungsmethode schreiben:

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

Dann kannst du schreiben:

if (sequence.IsEmpty())
81
Jon Skeet

Mit dieser Implementierung können Sie eine Erweiterungsmethode erstellen.

public static bool IsEmpty<T>(this IEnumerable<T> items) {
        using (var enumerator = items.GetEnumerator())
        {
            return !enumerator.MoveNext();
        }
 }
5

Nun, alle diese Methoden, die Sie aufrufen, sind LINQ-Erweiterungsmethoden. Es hängt also davon ab, wie der LINQ-Anbieter implementiert wurde. Wenn Sie wissen möchten, ob eine Sequenz leer ist, ist entweder Count() == 0 oder Any() == false geeignet. Ich bevorzuge Any() selbst.

Abhängig von der Art Ihres sequence-Typs müssen Sie jedoch möglicherweise keine LINQ-Erweiterungsmethode verwenden. Das heißt Wenn es sich um ein Array handelt, können Sie sequence.Length aufrufen. Wenn es sich um eine Sammlung handelt, können Sie sequence.Count verwenden.

2
Neil Barnwell

Ich verwende diese Erweiterungsmethoden, um zu erkennen, ob die Sequenz null ist oder kein Element enthält, und alternativ, um zu erkennen, ob die Sequenz mindestens ein Element enthält, ähnlich wie die string.IsNullOrEmpty() -Methode.

 public static bool IsNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
     if (source == null) {
        return true;
     }

     return !source.Any();
 }

 public static bool IsNotNullOrEmpty<TSource>(this IEnumerable<TSource> source) {
     return !source.IsNullOrEmpty();
 }
 .
 .
 .
 if (!sequence.IsNullOrEmpty()) {
     //Do Something with the sequence...
 }
0
Sagi

Du sagtest:

if(sequence.Count() == 0) Gute Lesbarkeit, aber schreckliche Leistung, da die gesamte Sequenz tatsächlich durchlaufen werden muss.

Ist das tatsächlich wahr? Sie sprechen über den Umgang mit einem Interface, IEnumerable<T>, und dennoch treffen Sie Annahmen bezüglich seiner Implementierung, die wahr sein können oder nicht. Tatsächlich behalten viele der benutzerdefinierten Sammlungen, die ich im Laufe der Jahre geschrieben habe, eine private Variable bei, in der der aktuelle Zähler intern gespeichert wird. Das Zurückgeben von .Count ist also eine triviale Angelegenheit, bei der nicht die gesamte Sammlung durchlaufen werden muss.

Wenn Sie also nicht wissen, dass eine bestimmte Implementierung für .Count schlecht optimiert ist, würde ich .Count verwenden. Vermeiden Sie nach Möglichkeit vorzeitige Optimierungen und achten Sie auf gute Lesbarkeit.

0
Nick

Eine Methode, die ich manchmal verwende, ist folgende:

if(!sequence.Any())

Dies muss (soweit ich weiß) nicht die ganze Sequenz durchlaufen, aber die lesbarkeit ist ein wenig rückwärts und umständlich. (Liest viel Besser, wenn wir überprüfen, dass die Sequenz nicht leer ist).

  1. Laut Microsoft muss Any tatsächlich nicht die gesamte Sequenz durchlaufen. Zitieren aus dem Abschnitt Bemerkungen:

Die Aufzählung von source wird angehalten, sobald das Ergebnis .__ sein kann. entschlossen.

  1. Dies gilt insbesondere, wenn Sie das Vorhandensein von Elementen in einer if-else-Anweisung prüfen. Lesbarkeit ist am besten, wenn man das Vorhandensein von Elementen in der if-Anweisung und das Fehlen von Elementen in der else testet, wodurch der !-Operator nicht verwendet wird:

    if (sequence.Any())
    {
    }
    else
    {
    }
    

    Die meisten würden das für lesbarer halten als:

    if (!sequence.Any())
    {
    }
    else
    {
    }
    
0
DavidRR