De retour 'IList' vs 'ICollection' vs 'Collection'
Je suis confus au sujet de ce qui type de collection que je reviens de mon API publique des méthodes et des propriétés.
Les collections que j'ai à l'esprit sont IList
, ICollection
et Collection
.
Est le retour de l'un de ces types toujours préféré aux autres, ou cela dépend-il de la situation spécifique?
Vous devez vous connecter pour publier un commentaire.
Généralement, vous devriez retourner un type qui est le plus général possible, c'est à dire celui qui sait juste assez de données retournées que le consommateur doit utiliser. De cette façon, vous avez plus de liberté pour changer la mise en œuvre de l'API, sans casser le code qui l'utilise.
Prendre aussi en considération la
IEnumerable<T>
interface comme type de retour. Si le résultat est uniquement destiné à être itéré, le consommateur n'a pas besoin de plus.Count
méthode vérifie le type réel de la collection, donc il va utiliser leLength
ouCount
propriétés pour certains types connus comme des tableaux etICollection
même lorsque vous les fournissez comme unIEnumerable
.Thing<T>
implémenteIList<T>
mais non pas le non-génériqueICollection
, puis de l'appel d'IEnumerable<Cat>.Count()
sur unThing<Cat>
serait rapide, mais en l'appelantIEnumerable<Animal>.Count()
serait lente (depuis l'extension de la méthode de rechercher et de trouver une mise en œuvre deICollection<Cat>
). Si la classe n'implémente la non-génériqueICollection
, cependant,IEnumerable<Animal>.Count
serait le trouver et l'utiliser.ICollection<T>
est une interface qui expose la collection de la sémantique commeAdd()
,Remove()
, etCount
.Collection<T>
est une mise en œuvre concrète de laICollection<T>
interface.IList<T>
est essentiellement unICollection<T>
avec un ordre aléatoire-fonction d'accès.Dans ce cas, vous devez décider si oui ou non vos résultats nécessitent de la liste de la sémantique comme l'ordre en fonction de l'indexation (puis utilisez
IList<T>
) ou si vous avez juste besoin de retourner un non ordonnée "sac" de résultats (puis utilisezICollection<T>
).Collection<T>
implémenteIList<T>
et pas seulementICollection<T>
.IEnumerable<T>
est commandé. Ce qui distingueIList<T>
deICollection<T>
est qu'il propose à ses membres de travailler avec les index. Par exemplelist[5]
fonctionne, maiscollection[5]
ne compile pas.IList<T>
. Il y a beaucoup de collections ordonnées qui ne le sont pas.IList<T>
est sur rapide un accès indexé.IList<T>
est un générique équivalent àIList
,ICollection<T>
etICollection
sont très différentes. Un génériqueFoo<T>
qui implémenteIList<T>
souvent de ne pas mettre en œuvre non génériqueIList
, mais doit encore mettre en œuvre les non-génériqueICollection
. Sinon, même siFoo<Cat>
serait la mise en œuvreIEnumerable<Animal>
etICollection<Cat>
, et le dernier exposer un rapideCount
propriété, laIEnumerable<Animal>.Count()
méthode d'extension ne serait pas en mesure d'utiliser leICollection<Cat>.Count()
mise en œuvre.ICollection<int> collection = new int[1]; Console.WriteLine(collection[0]);
. Je suppose que vous avez essayé avecCollection<T>
, pasICollection<T>
, mais ce n'est pas ce que je parlais.IEnumerable<T>
est commandé? PrendreHashSet<T>
- il implémenteIEnumerable<T>
mais n'est clairement pas commandé. I. e. vous n'avez aucune influence sur l'ordre des éléments et cet ordre peut changer à tout moment, si la table de hachage interne est organisé à nouveau.foreach
, vous obtenez les éléments dans un certain ordre, qui est définie par la collection.La principale différence entre
IList<T>
etICollection<T>
est queIList<T>
vous permet d'accéder à des éléments via un index.IList<T>
décrit semblable au tableau des types. Dans le cas d'uneICollection<T>
ne peuvent être accessibles que par le biais de l'énumération. Les deux permettent l'insertion et la suppression d'éléments.Si vous avez seulement besoin d'énumérer une collection, puis
IEnumerable<T>
est à privilégier. Il a deux avantages sur les autres:Il n'autorise pas les modifications de la collection (mais pas pour les objets référencés, si elles sont de type de référence).
Il permet la plus grande variété de sources, y compris les énumérations qui sont générées de manière algorithmique et ne sont pas des collections à tous.
Collection<T>
est une classe de base qui est principalement utile pour la mise en œuvre de collections. Si vous l'exposer dans les interfaces (Api), de nombreuses collections ne sont pas liés à elle sera exclue.Un inconvénient de
IList<T>
est que les piles de la mettre en œuvre, mais ne vous permet pas d'ajouter ou de supprimer des éléments (c'est à dire vous ne pouvez pas modifier la longueur du tableau). Une exception sera levée si vous appelezIList<T>.Add(item)
sur un tableau. La situation est quelque peu désamorcée commeIList<T>
a une propriété BooléenneIsReadOnly
que vous pouvez vérifier avant de tenter de le faire. Mais à mes yeux, c'est encore un défaut de conception dans la bibliothèque. Donc, j'utiliseList<T>
directement, lorsque la possibilité d'ajouter ou de supprimer des éléments est nécessaire.Collection
,ReadOnlyCollection
ouKeyedCollection
. Et queList
ne doivent pas être retournés.IList<T>
, il n'y a aucun moyen de s'assurer que la méthode ne sera pas appelé avec un tableau comme paramètre.IList<T>
est l'interface de base pour tous les génériques des listes. Puisque c'est une collection ordonnée, la mise en œuvre peut décider sur le bon de commande, allant de l'ordre de tri à l'ordre d'insertion. En outreIlist
a la propriété d'Élément qui permet à des méthodes pour lire et éditer des entrées dans la liste en fonction de leur index.Cela permet d'insérer, de supprimer une valeur dans la liste à un index de position.
Aussi depuis
IList<T> : ICollection<T>
, toutes les méthodes deICollection<T>
sont également disponibles pour la mise en œuvre.ICollection<T>
est l'interface de base pour tous les génériques des collections. Il définit la taille, les agents recenseurs et les méthodes de synchronisation. Vous pouvez ajouter ou supprimer un élément dans une collection, mais vous ne pouvez pas choisir à la position à laquelle il se produit en raison de l'absence de propriété index.Collection<T>
fournit une implémentationIList<T>
,IList
etIReadOnlyList<T>
.Si vous utilisez un étroit type d'interface tels que
ICollection<T>
au lieu deIList<T>
, vous protégez votre code contre la rupture des changements. Si vous utilisez un large type d'interface tels queIList<T>
, vous êtes plus en danger de rupture de modifications de code.Citant une source,
Retour d'un type d'interface est plus général, donc (à défaut de plus amples renseignements sur votre cas d'utilisation spécifiques), j'aurais pencher vers que. Si vous souhaitez exposer l'indexation de support, sélectionnez
IList<T>
, sinonICollection<T>
suffira. Enfin, si vous souhaitez indiquer que le retour de types sont en lecture seule, choisissezIEnumerable<T>
.Et, dans le cas où vous ne l'avez pas lu avant, Brad Abrams et Krzysztof Cwalina a écrit un grand livre intitulé "le Cadre des lignes Directrices de Conception: les Conventions, les Idiomes et les Modèles Réutilisables .Bibliothèques NET" (vous pouvez télécharger un résumé de ici).
IEnumerable<T>
est en lecture seule? Sûr, mais quand il faut relancer dans un contexte de référentiel, même après l'exécution de ToList n'est pas thread-safe. Problème, c'est quand la source de données d'origine devient GC, puis IEnumarble.ToList() ne fonctionne pas dans un contexte multithread. Il fonctionne sur un linéaire de un parce que GC est appelé après que vous faire le travail, mais à l'aide deasync
maintenant un jours à l'4.5+ IEnumarbale est en train de devenir un ballon mal.Il y a des sujets qui viennent de cette question:
Vous souhaitez peut-être mettre en évidence que c'est un Orientée Objet A. P. I.
interfaces versus classes
Si vous n'avez pas beaucoup d'expérience avec les interfaces, je vous recommande de tenir aux classes.
Je vois beaucoup de temps de développeurs de sauter à des interfaces, même si elle n'est pas necesarilly.
Et à la fin faire une mauvaise conception de l'interface, au lieu de, une bonne conception de classe,
qui, en passant, peut, éventuellement, être transféré dans une bonne conception de l'interface ...
Vous verrez beaucoup d'interfaces dans A. P. I., mais, ne vous précipitez pas pour elle,
si vous n'en avez pas besoin.
Vous finirez par apprendre comment appliquer les interfaces, à votre code.
qui classe spécifique, à partir de plusieurs comme les classes, de la collecte, de liste, de tableau ?
Il y a plusieurs classes en c# (dotnet) qui peuvent être interchangés. Comme déjà dit, si vous avez besoin de quelque chose à partir d'une classe plus spécifique, telle que "CanBeSortedClass", puis de la rendre explicite dans votre A. P. I..
Votre A. P. I. de l'utilisateur vraiment besoin de savoir que votre classe peut être triée, ou appliquer un format aux éléments ? Ensuite, utilisez le "CanBeSortedClass" ou "ElementsCanBePaintedClass",
sinon, utiliser "GenericBrandClass".
Sinon, utilisez une classe plus générale.
Commun des classes de collection versus paragraphe ("génériques") collections
Vous trouverez qu'il ya des classes qui contient d'autres éléments,
et vous pouvez spécifier que tous les éléments doivent être d'un type spécifique.
Générique Collections sont ceux des classes que vous pouvez utiliser la même collection,
pour plusieurs applications de code, sans avoir à créer une nouvelle collection,
pour chaque nouveau paragraphe, comme ceci: Collection.
Votre A. P. I. utilisateur va avoir besoin d'un type très particulier, de même pour tous les éléments ?
Utiliser quelque chose comme
List<WashingtonApple>
.Votre A. P. I. utilisateur va avoir besoin de plusieurs types ?
Exposer
List<Fruit>
pour votre A. P. I., et l'utilisationList<Orange>
List<Banana>
,List<Strawberry>
en interne, oùOrange
,Banana
etStrawberry
sont les descendants d'Fruit
.Votre A. P. I. utilisateur va avoir besoin d'un type générique de la collection ?
Utilisation
List
, où tous les éléments sontobject
(s).Acclamations.