107 votes

Propriété Count vs méthode Count() ?

En travaillant avec une collection, j'ai deux façons d'obtenir le nombre d'objets ; Count (le bien) et Count() (la méthode). Quelqu'un sait-il quelles sont les principales différences ?

Je peux me tromper, mais j'utilise toujours l'option Count dans toute déclaration conditionnelle, car je suppose que la propriété Count() effectue une sorte de requête sur la collection, alors que la méthode Count doit avoir déjà été attribué avant que je l'obtienne. Mais c'est une supposition - je ne sais pas si les performances seront affectées si je me trompe.

EDIT : Par curiosité alors, est-ce que Count() lancer une exception si la collection est nulle ? Parce que je suis presque sûr que le Count renvoie simplement 0.

9 votes

Tous deux lèveront une exception pour les collections nulles, parce qu'ils essaient tous deux d'appliquer l'approche de la . à quelque chose qui est nul.

140voto

Ian Nelson Points 20020

Décompilation de la source pour le Count() La méthode d'extension révèle qu'elle teste si l'objet est une ICollection (générique ou non) et, si c'est le cas, renvoie simplement l'identifiant de l'utilisateur. Count propriété :

Donc, si votre code accède à Count au lieu d'appeler Count() vous pouvez contourner la vérification du type - un avantage théorique en termes de performances, mais je doute qu'il soit perceptible !

// System.Linq.Enumerable
public static int Count<TSource>(this IEnumerable<TSource> source)
{
    checked
    {
        if (source == null)
        {
            throw Error.ArgumentNull("source");
        }
        ICollection<TSource> collection = source as ICollection<TSource>;
        if (collection != null)
        {
            return collection.Count;
        }
        ICollection collection2 = source as ICollection;
        if (collection2 != null)
        {
            return collection2.Count;
        }
        int num = 0;
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        return num;
    }
}

15 votes

+1 pour avoir pris l'initiative de faire de l'ingénierie inverse, très utile.

7 votes

Cependant, il faut garder à l'esprit que dans 3.5 Count() ne vérifie pas la présence de l'option non générique ICollection interface. Cette fonctionnalité n'a été ajoutée que dans .NET 4. Les versions 3.5 et 4 vérifient la présence de l'interface générique ICollection<T> interface.

4 votes

Appeler count sur une séquence sans éléments lèvera une exception. Mais Count() fonctionnera parfaitement.

43voto

AaronLS Points 12720

La performance n'est qu'une raison de choisir l'un ou l'autre. Choisir .Count() signifie que votre code sera plus générique. Il m'est arrivé de refacturer du code qui ne produisait plus une collection, mais quelque chose de plus générique comme un IEnumerable, mais d'autres codes étaient cassés en conséquence parce qu'ils dépendaient de .Count et j'ai dû le changer en .Count() . Si je mettais un point d'honneur à utiliser .Count() partout, le code sera probablement plus réutilisable et plus facile à maintenir. En général, le mieux est d'opter pour les interfaces les plus génériques si vous pouvez le faire. Par "plus générique", j'entends l'interface la plus simple qui est mise en œuvre par un plus grand nombre de types, ce qui vous assure une plus grande compatibilité entre les codes.

Je ne dis pas .Count() est meilleur, je dis simplement qu'il y a d'autres considérations qui concernent davantage la réutilisabilité du code que vous écrivez.

3 votes

+1 Ajout précieux à la discussion. Un code que je maintiens vient de se briser parce que la propriété .Count n'a pas survécu à une mise à jour de la version du HtmlAgilityPack.

2 votes

Cela peut être une arme à double tranchant. Que se passera-t-il si un jour quelqu'un essaie de modifier le IEnumerable pour en faire un véritable générateur. En regardant la base de code, je vois beaucoup d'endroits où la fonction .Count() suppose que l'énumérable peut être itéré plusieurs fois.

0 votes

@bashrc Vrai. Je pense que si l'on considère le changement du code du développeur par rapport au changement du code du framework, il est plus probable que le code du développeur change. Si ce genre de changement était fait dans le framework, cela casserait beaucoup de choses. Traditionnellement, ils introduisent de nouvelles collections/interfaces dans ces cas afin que les développeurs puissent migrer comme ils le souhaitent.

24voto

Lasse V. Karlsen Points 148037

El .Count() méthode puede être assez intelligent, ou connaître le type en question, et si oui, il puede utiliser le sous-jacent .Count propriété.

Mais bon, ça pourrait ne pas être le cas.

Je dirais qu'il est sûr de supposer que si la collection a une .Count La propriété elle-même sera votre meilleur atout en matière de performance.

Si le .Count() ne connaît pas la collection, elle l'énumérera, ce qui sera une opération O(n).

3 votes

Utilisation de la Count La propriété pourrait être meilleure, mais Count() méthode faire utiliser ICollection<T>.Count est en quelque sorte documenté ici : msdn.microsoft.com/fr/us/library/bb338038(v=vs.110).aspx

1 votes

Je ne sais pas comment tu sais presque tout.

5voto

AntonioR Points 446

Count() est une méthode d'extension qui permet d'itérer chaque élément d'un fichier IEnumerable<> et retourne combien d'éléments il y a. Si l'instance de IEnumerable est en fait un List<> il est donc optimisé pour renvoyer la valeur Count au lieu d'itérer tous les éléments.

0 votes

Même lorsque j'ai une List<>, j'utilise la méthode Count() pour garder mon code plus générique. C'est une bonne chose lorsque je refacture mes classes pour utiliser IEnumerable<> où il n'y a pas besoin d'une implémentation spécifique de la collection.

3voto

Dave C Points 228

S'il existe un Count o Length vous devez toujours la préférer à la propriété Count() qui itère généralement la collection entière pour compter le nombre d'éléments qu'elle contient. Il existe des exceptions lorsque la méthode Count() est par rapport à une source LINQ to SQL ou LINQ to Entities, par exemple, auquel cas elle effectue une requête de comptage sur la source de données. Même dans ce cas, s'il existe un Count il est préférable d'opter pour ce type de propriété, car elle a probablement moins de travail à faire.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X