web-dev-qa-db-fra.com

Comment vérifier si IEnumerable est null ou vide?

J'aime la méthode string.IsNullOrEmpty. J'aimerais avoir quelque chose qui permettrait la même fonctionnalité pour IEnumerable. Y a-t-il de tels? Peut-être une classe d'aide de collection? La raison pour laquelle je pose cette question est que, dans les déclarations if, le code semble encombré si le modèle est (mylist != null && mylist.Any()). Il serait beaucoup plus propre d'avoir Foo.IsAny(myList)

Cet article ne donne pas cette réponse: IEnumerable est vide? .

127
Schultz9999

Bien sûr que vous pourriez écrivez que:

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

cependant, veillez à ce que toutes les séquences ne soient pas répétables; généralement Je préfère ne les promener qu’une fois, au cas où.

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

Voici une version modifiée de la réponse utile de @Matt Greer qui inclut une classe wrapper statique afin que vous puissiez simplement le copier-coller dans un nouveau fichier source, ne dépend pas de Linq et ajoute une surcharge générique IEnumerable<T>, pour éviter la mise en boîte types qui se produiraient avec la version non générique. [EDIT: Notez que l'utilisation de IEnumerable<T> n'empêche pas la mise en boîte de l'énumérateur, duck-typing ne peut empêcher cela, mais au moins les éléments d'une collection à valeur typée ne seront pas encadrés.]

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

Une autre solution serait d’obtenir l’énumérateur et d’appeler la méthode MoveNext () pour voir s’il existe des éléments:

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

Cela fonctionne pour IEnumerable ainsi que IEnumerable <T>.

12
Darren

La façon dont je le fais, tirant parti de certaines fonctionnalités modernes de C #:

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();
    }
}

Et d'ailleurs, n'utilisez jamais Count == 0 ou Count() == 0 uniquement pour vérifier si une collection est vide. Toujours utiliser le .Any() de Linq

5
Ronald Rey

Cela peut aider

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;
}
4

À partir de C 6, vous pouvez utiliser la propagation null : myList?.Any() == true

Si vous trouvez toujours cela trop encombrant ou si vous préférez une bonne méthode d'extension, je recommanderais les réponses de Matt Greer et Marc Gravell, mais avec un peu de fonctionnalités étendues pour plus de détails. 

Leurs réponses offrent les mêmes fonctionnalités de base, mais dans une autre perspective. La réponse de Matt utilise la mentalité string.IsNullOrEmpty -, tandis que la réponse de Marc prend la route .Any() de Linq pour faire le travail.

Je suis personnellement enclin à utiliser la .Any() route, mais je voudrais ajouter la fonctionnalité de vérification des conditions de la méthode other overload :

    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);
    }

Ainsi, vous pouvez toujours faire des choses comme: myList.AnyNotNull(item=>item.AnswerToLife == 42); comme vous le feriez avec la .Any() régulière mais avec le contrôle nul ajouté

Notez qu'avec la méthode C # 6: myList?.Any() renvoie un bool? plutôt qu'un `bool, qui est l'effet réel de propagating null

3
Thomas Mulder

Voici le code de la réponse de Marc Gravell , avec un exemple d'utilisation.

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.");
        }
    }
}

Comme il le dit, toutes les séquences ne sont pas répétables, de sorte que le code peut parfois poser problème, car IsAny() commence à parcourir la séquence. Je soupçonne que la réponse de Robert Harvey voulait dire que vous n'avez souvent pas besoin de vérifier nullet vide. Souvent, vous pouvez simplement vérifier la valeur null et utiliser ensuite foreach.

Pour éviter de démarrer la séquence deux fois et tirer parti de foreach, je viens d'écrire du code comme celui-ci:

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.");
        }
    }
}

Je suppose que la méthode d'extension vous permet d'économiser quelques lignes de frappe, mais ce code me semble plus clair. Je suppose que certains développeurs ne se rendraient pas immédiatement compte que IsAny(items) commencera à parcourir la séquence. (Bien sûr, si vous utilisez beaucoup de séquences, vous apprendrez rapidement quelles étapes les franchir.)

2
Don Kirkby

J'utilise Bool IsCollectionNullOrEmpty = !(Collection?.Any()??false);. J'espère que cela t'aides.

Panne:

Collection?.Any() renverra null si Collection est null et false si Collection est vide.

Collection?.Any()??false nous donnera false si Collection est vide et false si Collection est null.

Un complément de cela nous donnera IsEmptyOrNull.

1

J'ai eu le même problème et je le résous comme: 

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

"c => c! = null" ignorera toutes les entités nulles.

1
Hosein Djadidi

J'ai construit ceci à partir de répondre par @Matt Greer

Il a parfaitement répondu à la question du PO.

Je voulais quelque chose comme ça tout en maintenant les capacités originales de Any tout en vérifiant la valeur null. Je poste ceci au cas où quelqu'un d'autre aurait besoin de quelque chose de similaire.

Plus précisément, je voulais toujours pouvoir transmettre un prédicat.

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);
    }
}

La dénomination de la méthode d'extension pourrait probablement être meilleure.

0
kb4000

Étant donné que certaines ressources sont épuisées après une lecture, je me suis demandé pourquoi ne pas combiner les contrôles et les lectures, au lieu du contrôle séparé traditionnel, puis lu.

Premièrement, nous en avons un pour l’extension en ligne plus simple à vérifier:

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();

Ensuite, nous avons un peu plus impliqué (enfin, du moins comme je l'ai écrit) l'extension inline check-for-null-and-empty:

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();

Bien entendu, vous pouvez toujours appeler les deux sans poursuivre la chaîne d’appel. De plus, j'ai inclus le paramName, de sorte que l'appelant puisse inclure un autre nom pour l'erreur s'il ne s'agit pas de "source", par exemple. "nom de (cible)".

0
Rob

J'ai utilisé simple si vérifier

découvrez ma solution

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

ajoutez simplement using System.Linq et constatez la magie qui se produit lorsque vous essayez d’accéder aux méthodes disponibles dans IEnumerable. Ajouter ceci vous donnera accès à la méthode nommée Count() aussi simple que cela. N'oubliez pas de vérifier null value avant d'appeler count() :)

0
Mohit

L'autre meilleure solution comme ci-dessous pour vérifier vide ou pas?

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

J'utilise celui-ci:

    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