web-dev-qa-db-fra.com

À quoi sert .Any () dans une liste C # <>?

J'en ai discuté avec des collègues et nous n'avons pas pu déterminer à quoi sert .Any pour un List<> Donné, en C #.

Vous pouvez vérifier la validité d'un élément dans le tableau comme l'instruction suivante:

if (MyList.Any()){ ...}  //Returns true or false

C'est exactement la même chose que

if (MyList.Count() != 0) { ... }

et est beaucoup plus courant, lisible et clair quant à l'intention de l'instruction if.

En fin de compte, nous étions coincés avec cette pensée:

.Any() peut être utilisé, fonctionnera tout aussi bien, mais est moins clair sur l'intention du programmeur, et dans ce cas, il ne devrait pas être utilisé.

Mais nous pensons que cela ne peut pas être vrai; nous devons manquer quelque chose.

Sommes nous?

44
Gil Sand

Gardez à l'esprit que Any ne fonctionne pas sur un List; il fonctionne sur un IEnumerable, qui représente un type concret qui peut ou non avoir une propriété Count. Il est vrai que ce n'est pas nécessairement la meilleure chose à utiliser sur un List, mais il est certainement utile à la fin d'une requête LINQ. Et encore plus utile que la version autonome est le remplacement qui prend un prédicat comme Where. Il n'y a rien de construit sur List qui soit aussi pratique ou expressif que la méthode d'extension prédicat -Any.

De plus, si vous utilisez Count() (la méthode d'extension LINQ pour IEnumerable), plutôt que Count (la propriété sur List), il peut avoir à énumérer l'intégralité séquence s'il ne peut pas optimiser cela en détectant que votre type de données sous-jacent a une propriété Count . Si vous avez une longue séquence, cela peut être un impact notable sur les performances lorsque vous ne vous souciez pas vraiment du nombre et que vous voulez simplement savoir s'il y en a articles de la collection.

99
Mason Wheeler

Il existe une différence de temps d'exécution Count() peut être O(n) où Any() est O (1).

56
Sign

En fait, gardez à l'esprit qu'il existe la propriété List.Count , puis la méthode Enumerable.Count .

Dans votre exemple, vous utilisez la méthode Enumerable.Count(), qui doit parcourir chaque élément de l'énumération pour renvoyer un résultat. C'est clairement plus lent que d'appeler Any() qui n'a besoin que d'itérer sur le premier élément, s'il existe.

MODIFIER:

Dans les commentaires, il a été souligné, à juste titre, que la méthode d'extension Enumerable.Count() n'a pas besoin de parcourir tous les éléments si elle détecte que l'énumérable se trouve également être un ICollection<T>. Donc, dans le cas d'un List<T>, l'utilisation de la propriété ou de la méthode Count ne fait aucune différence.

IEnumerable.Count source:

public static int Count<TSource>(this IEnumerable<TSource> source) {
    if (source == null) throw Error.ArgumentNull("source");
    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null) return collectionoft.Count;
    ICollection collection = source as ICollection;
    if (collection != null) return collection.Count;
    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator()) {
        checked {
            while (e.MoveNext()) count++;
        }
    }
    return count;
}
9
sstan

Une question surprenante - je trouve que l'intention de list.Any() est beaucoup plus claire que l'intention de list.Count()!=0.

L'intention signifie: si vous lisez le code de quelqu'un (et que vous ne l'avez pas écrit vous-même), est-il complètement évident ce que le programmeur veut réaliser et pourquoi il a écrit écrit tel quel? Si un problème commun est résolu d'une manière inutilement complexe, vous devenez immédiatement suspect et vous vous demandez pourquoi le développeur n'a pas utilisé la méthode simple. Vous parcourez le code et essayez de voir si vous avez oublié quelque chose. Vous avez peur de modifier le code, car vous craignez qu'il manque un effet secondaire et sa modification peut entraîner des problèmes inattendus.

L'intention d'utiliser la méthode Any() est complètement claire - vous voulez savoir s'il y a des éléments dans la liste ou non.

L'intention de l'expression Count()!=0 d'autre part n'est pas évidente pour le lecteur. Il n'est bien sûr pas difficile de voir que l'expression vous indique si la liste est vide ou non. Les questions se posent parce que vous l'écrivez de cette façon plutôt que d'utiliser la méthode standard. Pourquoi utilisez-vous explicitement Count()? Si vous avez juste besoin de savoir s'il y a des éléments any dans une liste, pourquoi voulez-vous d'abord compter la liste entière? Dès que vous atteignez 1, vous avez déjà votre réponse. Si la source était un itérateur sur une grande collection (peut-être infinie) ou est traduite en sql, cela pourrait faire une grande différence en termes de performances. Alors peut-être que l'utilisation explicite de Count () est de forcer une requête différée à s'exécuter ou à traverser un itérateur?

Mais la source est en fait un List<T>Count() est O(1) et n'a aucun effet secondaire. Mais si le code se fonde sur cette propriété de List<T>, Alors pourquoi ne pas utiliser la propriété Count- qui indique plus clairement que vous vous attendez à une opération O(1) sans effets secondaires?

Telle qu'elle est écrite, list.Count()!=0 fait exactement la même chose que list.Any() sauf qu'elle est inutilement plus complexe et que l'intention n'est pas claire.

6
JacquesB

C'est peut-être juste le mot? Any est un adjectif, ne disant vraiment rien. Venant de Java, je l'appellerais isNonEmpty qui contient un verbe. Un type SQL pourrait préférer EXISTS. Mais peut-être que Any correspond le mieux au système C #.

Quel que soit le choix de Word, une fois que vous vous y êtes habitué, il doit être beaucoup plus clair. Souhaitez-vous demander "Y a-t-il more than zero bouteilles de bière restantes ". Vous attendriez-vous one or more personnes commençant à les compter avant de répondre "Non, il n'y a pas any"?

2
maaartinus