it-swarm.com.de

Wie kann ich überprüfen, ob IEnumerable null oder leer ist?

Ich liebe string.IsNullOrEmpty Methode. Ich hätte gerne etwas, was die gleiche Funktionalität für IEnumerable erlaubt. Gibt es so etwas? Vielleicht eine Sammelhelferklasse? Der Grund, warum ich frage, ist, dass in if-Anweisungen der Code unübersichtlich wirkt, wenn der Muster (mylist != null && mylist.Any()) ist. Es wäre viel sauberer, Foo.IsAny(myList) zu haben. 

Dieser Beitrag gibt diese Antwort nicht: IEnumerable ist leer? .

127
Schultz9999

Sicher, Sie könnten schreiben das:

public static class Utils {
    public static bool IsAny<T>(this IEnumerable<T> data) {
        return data != null && data.Any();
    }
}

seien Sie jedoch vorsichtig, dass nicht alle Sequenzen wiederholbar sind. allgemein Ich gehe sie nur einmal, nur für den Fall.

170
Marc Gravell
public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable) {
    return enumerable == null || !enumerable.Any();
}
113
Matt Greer

Hier ist eine modifizierte Version von @Matt Greers nützlicher Antwort, die eine statische Wrapper-Klasse enthält, sodass Sie diese einfach kopieren und in eine neue Quelldatei einfügen können, nicht von Linq abhängig ist und eine generische IEnumerable<T>-Überladung hinzufügt, um das Einbetten von Werten zu vermeiden Typen, die mit der nicht generischen Version auftreten würden. [BEARBEITEN: Beachten Sie, dass die Verwendung von IEnumerable<T> das Boxen des Enumerators nicht verhindert. duck-typing kann das nicht verhindern, aber zumindest werden die Elemente in einer Werttyp-Auflistung nicht jeweils mit einem Box versehen.]

using System.Collections;
using System.Collections.Generic;

public static class IsNullOrEmptyExtension
{
    public static bool IsNullOrEmpty(this IEnumerable source)
    {
        if (source != null)
        {
            foreach (object obj in source)
            {
                return false;
            }
        }
        return true;
    }

    public static bool IsNullOrEmpty<T>(this IEnumerable<T> source)
    {
        if (source != null)
        {
            foreach (T obj in source)
            {
                return false;
            }
        }
        return true;
    }
}
19
yoyo

Eine andere Möglichkeit wäre, den Enumerator abzurufen und die MoveNext () - Methode aufzurufen, um festzustellen, ob Elemente vorhanden sind:

if (mylist != null && mylist.GetEnumerator().MoveNext())
{
    // The list is not null or empty
}

Dies funktioniert sowohl für IEnumerable als auch für IEnumerable <T>.

12
Darren

So wie ich das mache, um einige moderne C # -Funktionen zu nutzen:

Option 1)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any() ?? false);
    }
}

Option 2)

public static class Utils {
    public static bool IsNullOrEmpty<T>(this IEnumerable<T> list) {
        return !(list?.Any()).GetValueOrDefault();
    }
}

Übrigens verwenden Sie niemals Count == 0 oder Count() == 0, nur um zu überprüfen, ob eine Sammlung leer ist. Verwenden Sie immer Linqs .Any()

5
Ronald Rey

Das kann helfen

public static bool IsAny<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() == true;
}

public static bool IsNullOrEmpty<T>(this IEnumerable<T> enumerable)
{
    return enumerable?.Any() != true;
}

Beginnend mit C # 6 können Sie null propagation : myList?.Any() == true verwenden.

Wenn Sie dies immer noch als zu verstopft empfinden oder eine gute alte Erweiterungsmethode bevorzugen, würde ich die Antworten von Matt Greer und Marc Gravell empfehlen, die jedoch der Vollständigkeit halber etwas erweitert sind. 

Ihre Antworten bieten die gleiche Grundfunktionalität, jedoch jeweils aus einer anderen Perspektive. Matts Antwort verwendet die Mentalität string.IsNullOrEmpty -, während Marcs Antwort Linqs .Any()-Weg einnimmt, um die Arbeit zu erledigen.

Ich bin persönlich geneigt, die .Any() road zu verwenden, möchte aber die Condition-Checking-Funktionalität aus der anderen Überladung der Methode hinzufügen :

    public static bool AnyNotNull<T>(this IEnumerable<T> source, Func<T, bool> predicate = null)
    {
        if (source == null) return false;
        return predicate == null
            ? source.Any()
            : source.Any(predicate);
    }

Sie können also immer noch folgende Aktionen ausführen: myList.AnyNotNull(item=>item.AnswerToLife == 42); wie mit der regulären .Any(), jedoch mit der hinzugefügten Nullprüfung

Beachten Sie beim C # 6-Verfahren: myList?.Any() gibt einen bool? statt eines `bool 'zurück. Dies ist die tatsächliche Auswirkung von propagating null

3
Thomas Mulder

Hier ist der Code aus Marc Gravells Antwort , zusammen mit einem Beispiel für die Verwendung.

using System;
using System.Collections.Generic;
using System.Linq;

public static class Utils
{
    public static bool IsAny<T>(this IEnumerable<T> data)
    {
        return data != null && data.Any();
    }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        if (items.IsAny())
        {
            foreach (var item in items)
            {
                Console.WriteLine(item);
            }
        }
        else
        {
            Console.WriteLine("No items.");
        }
    }
}

Wie er sagt, sind nicht alle Sequenzen wiederholbar, so dass Code manchmal Probleme verursachen kann, da IsAny() die Sequenz durchläuft. Ich vermute, was Robert Harveys Antwort bedeutete, war, dass Sie häufig nicht nach nullund suchen müssen. Oft können Sie einfach nach Null suchen und dann foreach verwenden.

Um zu vermeiden, die Sequenz zweimal zu starten und foreach zu nutzen, habe ich einfach folgenden Code geschrieben:

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<string> items;
        //items = null;
        //items = new String[0];
        items = new String[] { "foo", "bar", "baz" };

        /*** Example Starts Here ***/
        bool isEmpty = true;
        if (items != null)
        {
            foreach (var item in items)
            {
                isEmpty = false;
                Console.WriteLine(item);
            }
        }
        if (isEmpty)
        {
            Console.WriteLine("No items.");
        }
    }
}

Ich denke, die Erweiterungsmethode erspart Ihnen ein paar Zeilen Eingabe, aber dieser Code erscheint mir klarer. Ich vermute, dass einige Entwickler nicht sofort merken würden, dass IsAny(items) tatsächlich durch die Sequenz geht. (Natürlich, wenn Sie viele Sequenzen verwenden, lernen Sie schnell, über die einzelnen Schritte nachzudenken.)

2
Don Kirkby

Ich benutze Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);. Hoffe das hilft.

Nervenzusammenbruch:

Collection?.Any() gibt null zurück, wenn Collection null ist, und false, wenn Collection leer ist.

Collection?.Any()??false gibt uns false, wenn Collection leer ist, und false, wenn Collection null ist.

Die Ergänzung dazu wird uns IsEmptyOrNull geben.

Ich hatte das gleiche Problem und löste es wie folgt: 

    public bool HasMember(IEnumerable<TEntity> Dataset)
    {
        return Dataset != null && Dataset.Any(c=>c!=null);
    }

"c => c! = null" ignoriert alle Nullentitäten.

1
Hosein Djadidi

Ich habe dies aus der Antwort von @Matt Greer gebaut

Er hat die Frage des OP perfekt beantwortet.

Ich wollte etwas Ähnliches, während ich die ursprünglichen Fähigkeiten von Any beibehielt, während ich auch auf Null prüfe. Ich poste dies, falls jemand anderes etwas Ähnliches braucht.

Konkret wollte ich noch ein Prädikat übergeben.

public static class Utilities
{
    // Will return true if it is not null and contains elements.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable)
    {
        return enumerable != null && enumerable.Any();
    }

    // Will return true if it is not null and contains elements that satisfy the condition.
    public static bool NotNullAny<T>(this IEnumerable<T> enumerable, Func<T, bool> predicate)
    {
        return enumerable != null && enumerable.Any(predicate);
    }
}

Die Benennung der Erweiterungsmethode könnte wahrscheinlich besser sein.

0
kb4000

Da einige Ressourcen nach einem Lesevorgang erschöpft sind, habe ich mir überlegt, warum nicht die Prüfungen und Lesevorgänge anstelle der herkömmlichen getrennten Prüfung kombiniert und dann gelesen werden.

Zuerst haben wir eine für die einfachere Check-for-Null-Inline-Erweiterung:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNull<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null) => source ?? throw new System.ArgumentNullException(paramName ?? nameof(source));

var first = source.ThrowOnNull().First();

Dann haben wir ein wenig mehr damit zu tun (na ja, zumindest so, wie ich es geschrieben habe), die Inline-Erweiterung auf Null und Leer zu prüfen:

public static System.Collections.Generic.IEnumerable<T> ThrowOnNullOrEmpty<T>(this System.Collections.Generic.IEnumerable<T> source, string paramName = null)
{
  using (var e = source.ThrowOnNull(paramName).GetEnumerator())
  {
    if (!e.MoveNext())
    {
      throw new System.ArgumentException(@"The sequence is empty.", paramName ?? nameof(source));
    }

    do
    {
      yield return e.Current;
    }
    while (e.MoveNext());
  }
}

var first = source.ThrowOnNullOrEmpty().First();

Sie können natürlich trotzdem beide anrufen, ohne die Anrufkette fortzusetzen. Außerdem habe ich den paramName eingefügt, damit der Aufrufer einen alternativen Namen für den Fehler einfügen kann, wenn nicht "source" überprüft wird, z. msgstr "nameof (Ziel)".

0
Rob

Ich habe einfach nachgefragt, ob ich nachsehen möchte

schau dir meine Lösung an

foreach (Pet pet in v.Pets)
{
    if (pet == null)
    {
        Console.WriteLine(" No pet");// enumerator is empty
        break;
    }
    Console.WriteLine("  {0}", pet.Name);
}
0

fügen Sie einfach using System.Linq hinzu und sehen Sie die Magie, wenn Sie versuchen, auf die verfügbaren Methoden in der IEnumerable zuzugreifen. Wenn Sie dies hinzufügen, erhalten Sie Zugriff auf die Methode Count(), die so einfach ist. Denken Sie daran, vor dem Aufruf von count() :) nach null value zu suchen.

0
Mohit

Die andere beste Lösung wie unten, leer zu überprüfen oder nicht?

for(var item in listEnumerable)
{
 var count=item.Length;
  if(count>0)
  {
         // not empty or null
   }
  else
  {
       // empty
  }
}
0
Shakeer Hussain
if (collection?.Any() == true){
    // if collection contains more than one item
}
if (collection?.Any() != true){
    // if collection is null
    // if collection does not contain any item
}
0
Scholtz

Ich benutze diesen:

    public static bool IsNotEmpty(this ICollection elements)
    {
        return elements != null && elements.Count > 0;
    }

Ejem:

List<string> Things = null;
if (Things.IsNotEmpty())
{
    //replaces ->  if (Things != null && Things.Count > 0) 
}
0
Jhollman