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
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())
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();
}
}
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
.
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é.
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).
L'énumération de
source
est arrêtée dès que le résultat peut être déterminé.
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
{
}