web-dev-qa-db-fra.com

Méthode recommandée pour vérifier si une séquence est vide

Une méthode retourne une séquence, IEnumerable<T>, et vous voulez maintenant vérifier si elle est vide. Comment recommandez-vous cela? Je recherche à la fois une bonne lisibilité et de bonnes performances. 

La première et la plus évidente consiste à vérifier que le nombre est supérieur à zéro:

if(sequence.Count() == 0)

A une lisibilité décente, mais une performance épouvantable car il doit passer par toute la séquence.

Une méthode que j'utilise parfois est la suivante:

if(!sequence.Any())

Pour autant que je sache, cela ne doit pas nécessairement passer par toute la séquence, mais la lisibilité est un peu en arrière et maladroite. (Lit beaucoup mieux si nous vérifions que la séquence est not vide cependant).

Une autre option consiste à utiliser First dans un try-catch, comme ceci:

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

Pas une très jolie solution, et probablement plus lente aussi, car elle utilise des exceptions et d'autres choses. Cela pourrait éviter cela en utilisant bien sûr FirstOrDefault, sauf que vous auriez un gros problème si le premier élément de la séquence en fait était la valeur par défaut;)

Alors, y a-t-il d'autres moyens de vérifier si une séquence est vide? Lequel utilisez-vous habituellement? Lequel recommandez-vous d'utiliser?

Remarque: Pour une lisibilité optimale, je mettrais probablement l'un des extraits ci-dessus dans une méthode d'extension IsEmpty, mais je suis toujours curieux, car je devrais également faire quelque chose à l'intérieur de cette méthode: p

46
Svish

Je voudrais utiliser !sequence.Any(), personnellement.

Si vous vraiment avez besoin de, vous pouvez toujours écrire votre propre méthode d'extension:

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

Ensuite, vous pouvez écrire:

if (sequence.IsEmpty())
81
Jon Skeet

Vous pouvez créer une méthode d'extension avec cette implémentation.

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

Toutes ces méthodes que vous appelez sont des méthodes d’extension LINQ. Cela dépend donc de la façon dont le fournisseur LINQ a été implémenté. Si vous voulez savoir si une séquence est vide, Count() == 0 ou Any() == false est approprié. Je préfère Any() moi-même.

Toutefois, selon le type de votre sequence, vous n’avez peut-être pas besoin d’utiliser une méthode d’extension LINQ. C'est à dire. si c'est un tableau, vous pouvez appeler sequence.Length. Si c'est une collection, vous pouvez utiliser sequence.Count.

2
Neil Barnwell

Tu as dit:

if(sequence.Count() == 0) A une lisibilité décente, mais une performance épouvantable car il doit passer par toute la séquence.

Est-ce vraiment vrai? Vous parlez de traiter avec un Interface , IEnumerable<T>, et pourtant, vous faites des hypothèses concernant son implémentation qui peuvent ou non être vraies. En fait, bon nombre des collections personnalisées que j'ai écrites au cours des années conservent une variable privée qui stocke le nombre actuel en interne, ce qui signifie que renvoyer .Count est une opération triviale qui ne nécessite pas l'itération de la collection.

Cela dit, à moins que vous ne sachiez qu'une implémentation spécifique est mal optimisée pour .Count, j'utiliserais .Count. Évitez autant que possible l'optimisation prématurée et limitez-vous à la lisibilité.

0
Nick

Une méthode que j'utilise parfois est la suivante:

if(!sequence.Any())

Pour autant que je sache, cela ne doit pas nécessairement passer par toute la séquence, mais la lisibilité est un peu en arrière et maladroite. (Lit beaucoup Mieux si nous vérifions que la séquence n'est pas vide cependant).

  1. Selon Microsoft, Any is not doit en effet passer par toute la séquence. Citant de la section Remarques:

L'énumération de source est arrêtée dès que le résultat peut être déterminé.

  1. Cela est particulièrement vrai lorsque vous testez la présence d'éléments dans une instruction if-else. On peut soutenir que la lisibilité est meilleure si on teste la présence d'éléments dans l'instruction if et l'absence d'éléments dans la variable else, évitant ainsi l'utilisation de l'opérateur !:

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

    La plupart considéreraient cela plus lisible que:

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