web-dev-qa-db-fra.com

C #: différence entre la liste <T> et la collection <T> (CA1002, Ne pas exposer les listes génériques)

J'ai essayé d'exécuter Run Code Analysis sur un projet ici, et j'ai reçu un certain nombre d'avertissements qui disaient quelque chose comme ceci:

CA1002: Microsoft.Design: modifiez 'List <SomeType>' in 'SomeClass.SomeProtectedOrPublicProperty' pour utiliser Collection, ReadOnlyCollection ou KeyedCollection

Pourquoi devrais-je utiliser Collection<T> Au lieu de List<T>? Quand je regarde la documentation msdn, elles semblent presque égales. Après avoir lu l'aide sur l'erreur pour l'avertissement, j'ai constaté que

System.Collections.Generic.List (T) _ est une collection générique conçue pour les performances et non l'héritage et, par conséquent, ne contient aucun membre virtuel.

Mais qu'est-ce que cela signifie vraiment? Et que dois-je faire à la place?

Dois-je continuer à utiliser List<T> En interne, puis dans les propriétés retourner un new Collection<T>(someList) à la place? Ou devrais-je simplement commencer à utiliser Collection<T> Au lieu de List<T>?

94
Svish

En bref, la liste générique n'a pas de méthodes virtuelles pour ajouter, supprimer, etc., car elle a été conçue pour être rapide et non extensible. Cela signifie que vous ne pouvez pas échanger cette implémentation concrète contre une sous-classe utile (même si vous pouvez la sous-classer car elle n'est pas scellée).

Par conséquent, en exposant la liste elle-même, vous ne pouvez jamais étendre votre collection pour suivre les opérations d'ajout ou de suppression (par exemple) sans rompre le contrat public de la classe.

En exposant votre collection en tant qu'IList ou autre, vous pouvez toujours utiliser la liste en tant que magasin de sauvegarde réel, mais vous conservez une extensibilité future car vous pourrez échanger l'implémentation concurrente plus tard sans modifier le contrat public de votre classe.

137
Rob Levine

Collection expose certains membres virtuels (insérer, supprimer, définir, effacer) que vous pouvez remplacer et fournir des fonctionnalités supplémentaires (telles que les événements de notification) lorsque la collection est modifiée.

Vous n'avez peut-être pas besoin de cela maintenant, mais c'est une exigence courante pour les classes qui contiennent des collections, il est donc préférable de le planifier à l'avance. Parce que Collection est conçu avec une extensibilité à l'esprit, il est très flexible. Si à l'avenir vous décidez que vous avez besoin d'une fonctionnalité supplémentaire dans la collection, vous pouvez simplement l'étendre sans aucune modification de l'interface publique de la classe. Si vous aviez utilisé une liste, vous auriez dû la changer en une collection ce qui signifie qu'elle aurait cassé tous les appelants de votre classe car ils devraient être modifiés pour utiliser des listes.

List d'autre part est conçu en pensant aux performances, il ne doit donc être utilisé que dans des cas spécifiques où les performances sont très importantes. Parce qu'il n'est pas extensible, les modifications futures apportées à quoi que ce soit à l'aide d'une liste briseront tout le reste qui en dépend. Normalement, List ne doit être utilisé qu'en interne dans des classes de très bas niveau et ne doit être exposé à rien pour réduire les risques de modifications futures.

24
Simon P Stevens