web-dev-qa-db-fra.com

Retour de 'IList' vs 'ICollection' vs 'Collection'

Je ne comprends pas quel type de collection je devrais renvoyer de mes méthodes et propriétés de l'API publique.

Les collections que j'ai à l'esprit sont IList, ICollection et Collection.

Est-ce que le retour de l'un de ces types est toujours préféré aux autres, ou cela dépend-il de la situation spécifique?

105
Rocky Singh

En règle générale, vous devez renvoyer un type aussi général que possible, c’est-à-dire qui connaît suffisamment le nombre de données renvoyées que le consommateur doit utiliser. De cette façon, vous avez une plus grande liberté pour modifier l'implémentation de l'API, sans casser le code qui l'utilise.

Considérez aussi le IEnumerable<T> interface en tant que type de retour. Si le résultat doit seulement être itéré, le consommateur n'a pas besoin de plus que cela.

66
Guffa

ICollection<T> Est une interface qui expose la sémantique de la collection, telle que Add(), Remove() et Count.

Collection<T> Est une implémentation concrète de l'interface ICollection<T>.

IList<T> Est essentiellement un ICollection<T> Avec un accès aléatoire.

Dans ce cas, vous devez décider si vos résultats nécessitent ou non une sémantique de liste, telle que l'indexation basée sur les commandes (utilisez ensuite IList<T>), Ou si vous devez simplement renvoyer un "sac" de résultats non ordonné (puis utilisez ICollection<T>).

128
cordialgerm

La principale différence entre IList<T> Et ICollection<T> Est que IList<T> Vous permet d'accéder aux éléments via un index. IList<T> Décrit les types de type tableau. Les éléments d'un ICollection<T> Ne sont accessibles que par énumération. Les deux permettent l'insertion et la suppression d'éléments.

Si vous avez seulement besoin d'énumérer une collection, alors IEnumerable<T> Doit être préféré. Il présente deux avantages par rapport aux autres:

  1. Il n'autorise aucune modification de la collection (mais pas des objets référencés s'ils sont de type référence).

  2. Cela permet la plus grande variété possible de sources, y compris les énumérations générées par algorithme et qui ne sont pas du tout des collections.

Collection<T> Est une classe de base principalement utile aux développeurs de collections. Si vous l'exposez dans des interfaces (API), de nombreuses collections utiles n'en dérivant pas seront exclues.


Un inconvénient de IList<T> Est que les tableaux l'implémentent, mais ne vous permettent pas d'ajouter ou de supprimer des éléments (c'est-à-dire que vous ne pouvez pas changer la longueur du tableau). Une exception sera levée si vous appelez IList<T>.Add(item) sur un tableau. La situation est quelque peu désamorcée car IList<T> A une propriété booléenne IsReadOnly que vous pouvez vérifier avant d'essayer de le faire. Mais à mes yeux, c'est toujours un défaut de conception dans la bibliothèque. Par conséquent, j'utilise directement List<T>, Lorsque la possibilité d'ajouter ou de supprimer des éléments est requise.

56

IList<T> est l'interface de base de toutes les listes génériques. S'agissant d'une collection ordonnée, l'implémentation peut décider de l'ordre, allant de l'ordre trié à l'ordre d'insertion. De plus, Ilist a la propriété Item qui permet aux méthodes de lire et d’éditer les entrées de la liste en fonction de leur index. Cela permet d'insérer, de supprimer une valeur dans/de la liste à un index de position.

Aussi depuis IList<T> : ICollection<T>, toutes les méthodes de ICollection<T> sont également disponibles ici pour la mise en œuvre.

ICollection<T> est l'interface de base de toutes les collections génériques. Il définit la taille, les énumérateurs et les méthodes de synchronisation. Vous pouvez ajouter ou supprimer un élément dans une collection, mais vous ne pouvez pas choisir à quelle position il se produit en raison de l'absence de propriété d'index.

Collection<T> fournit une implémentation pour IList<T>, IList et IReadOnlyList<T>.

Si vous utilisez un type d'interface plus étroit tel que ICollection<T> au lieu de IList<T>, vous protégez votre code contre les changements brusques. Si vous utilisez un type d'interface plus large tel que IList<T>, vous êtes plus en danger de casser les changements de code.

Citant un source ,

ICollection, ICollection<T>: Vous souhaitez modifier la collection ou vous souciez de sa taille. IList, IList<T>: Vous souhaitez modifier la collection et vous vous souciez de la commande et/ou du positionnement des éléments dans la collection.

6
NullReference

Le retour d'un type d'interface est plus général, donc (sans informations supplémentaires sur votre cas d'utilisation spécifique), je m'approcherais de cela. Si vous souhaitez exposer la prise en charge de l'indexation, choisissez IList<T>, autrement ICollection<T> suffira. Enfin, si vous souhaitez indiquer que les types renvoyés sont en lecture seule, choisissez IEnumerable<T>.

Et, au cas où vous ne l'auriez pas lu auparavant, Brad Abrams et Krzysztof Cwalina ont écrit un excellent livre intitulé "Framework Design Guidelines: Conventions, idiomes et modèles pour les bibliothèques .NET réutilisables" (vous pouvez télécharger un résumé à partir de ici ).

4
Alan