Habituellement, ce que vous choisissez dépend des méthodes auxquelles vous devez accéder. En général - IEnumerable<>
(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx ) pour une liste des objets qui doivent uniquement être itérés via, ICollection<>
(MSDN: http: // msdn.microsoft.com/en-us/library/92t2ye13.aspx ) pour une liste des objets qui doivent être itérés et modifiés, List<>
pour une liste des objets qui doivent être itérés, modifiés, triés, etc. (voir ici pour une liste complète: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx ).
D'un point de vue plus spécifique, le chargement paresseux entre en jeu avec le choix du type. Par défaut, les propriétés de navigation dans Entity Framework sont fournies avec le suivi des modifications et sont des proxys. Pour que le proxy dynamique soit créé en tant que propriété de navigation, le type virtuel doit implémenter ICollection
.
Une propriété de navigation qui représente l'extrémité "plusieurs" d'une relation doit renvoyer un type qui implémente ICollection, où T est le type de l'objet à l'autre extrémité de la relation. - Conditions requises pour la création de proxy POCO MSDN
Plus d'informations sur la définition et la gestion des relations MSDN
List
devrait être beaucoup mieux, ouais?List
beaucoup. Bien qu'il ait le plus de frais généraux, il offre le plus de fonctionnalités.private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
utilise la même mémoire queprivate List<int> _integers = new List<int> { 1, 2, 3 };
List<T>
possède uneGetEnumerator()
méthode, distincte de son implémentation deIEnumerable<T>
, qui renvoie un type de structure mutableList<T>.Enumerator
. Dans la plupart des contextes, ce type donnera des performances légèrement meilleures qu'un objet de segment de mémoire autonome. Les compilateurs dont les énumérateurs de type canard (comme le font C # et vb.net) peuvent en profiter lors de la génération deforeach
code. Si leList<T>
est converti enIEnumrable<T>
avant leforeach
, laIEnumerable<T>.GetEnumerator()
méthode retournera un objet alloué au tas, rendant l'optimisation impossible.ICollection<T>
est utilisé car l'IEnumerable<T>
interface ne fournit aucun moyen d'ajouter des éléments, de supprimer des éléments ou de modifier autrement la collection.la source
List<T>
met en œuvreICollection<T>
.ICollection
ne permet aucun moyen d'ajouter des éléments, mais c'est toujours un complément utileIEnumerable<T>
car il fournit unCount
membre qui est généralement beaucoup plus rapide que d'énumérer tout. Notez que si unIList<Cat>
ouICollection<Cat>
est passé au code qui attend unIEnumerable<Animal>
, laCount()
méthode d'extension sera rapide si elle implémente le non génériqueICollection
, mais pas si elle implémente uniquement les interfaces génériques car un typiqueICollection<Cat>
ne l'implémentera pasICollection<Animal>
.Répondre à votre question sur
List<T>
:List<T>
est une classe; la spécification d'une interface permet une plus grande flexibilité d'implémentation. Une meilleure question est "pourquoi pasIList<T>
?"Pour répondre à cette question, considérez ce qui
IList<T>
s'ajoute àICollection<T>
: l'indexation entière, ce qui signifie que les éléments ont un ordre arbitraire et peuvent être récupérés par référence à cet ordre. Cela n'est probablement pas significatif dans la plupart des cas, car les articles doivent probablement être commandés différemment dans différents contextes.la source
Il existe des différences de base entre ICollection et IEnumerable
Programme simple:
la source
Je m'en souviens de cette façon:
IEnumerable a une méthode GetEnumerator () qui permet de lire les valeurs d'une collection sans y écrire. La plupart de la complexité de l'utilisation de l'énumérateur est prise en charge pour nous par le pour chaque instruction en C #. IEnumerable a une propriété: Current, qui renvoie l'élément actuel.
ICollection implémente IEnumerable et ajoute quelques propriétés supplémentaires dont la plus utilisée est Count. La version générique de ICollection implémente les méthodes Add () et Remove ().
IList implémente à la fois IEnumerable et ICollection et ajoute l'accès d'indexation d'entier aux éléments (ce qui n'est généralement pas requis, car la commande est effectuée dans la base de données).
la source
L'idée de base de l'utilisation
ICollection
est de fournir une interface pour accéder en lecture seule à une quantité limitée de données. En fait, vous avez une propriété ICollection.Count .IEnumerable
convient mieux à une chaîne de données où vous lisez jusqu'à un certain point logique, une condition spécifiée explicitement par le consommateur ou jusqu'à la fin de l'énumération.la source
ICollection
est en lecture seule alors qu'ilICollection<T>
ne l'est pas.Les propriétés de navigation sont généralement définies comme virtuelles afin qu'elles puissent tirer parti de certaines fonctionnalités d'Entity Framework telles que le chargement paresseux.
Si une propriété de navigation peut contenir plusieurs entités (comme dans les relations plusieurs-à-plusieurs ou un-à-plusieurs), son type doit être une liste dans laquelle des entrées peuvent être ajoutées, supprimées et mises à jour, comme ICollection.
https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net- application mvc
la source
Ce que j'ai fait dans le passé, c'est déclarer mes collections de classes internes en utilisant
IList<Class>
,ICollection<Class>
ouIEnumerable<Class>
(si la liste est statique) selon que je devrai ou non effectuer un certain nombre des opérations suivantes dans une méthode de mon référentiel: énumérer, trier / ordonner ou modifier . Lorsque j'ai juste besoin d'énumérer (et peut-être de trier) des objets, je crée un tempList<Class>
pour travailler avec la collection dans une méthode IEnumerable. Je pense que cette pratique ne serait efficace que si la collection est relativement petite, mais cela peut être une bonne pratique en général, idk. Veuillez me corriger s'il existe des preuves expliquant pourquoi cela ne serait pas une bonne pratique.la source
Essayons de penser en dehors de la boîte avec / par logique et de comprendre clairement ces trois interfaces dans votre question:
Lorsque la classe d'une instance implémente l'interface System.Collection.IEnumerable, en termes simples, nous pouvons dire que cette instance est à la fois énumérable et itérable, ce qui signifie que cette instance permet en quelque sorte dans une seule boucle d'aller / obtenir / passer / traverser / itérer sur / à travers tous les éléments et éléments que cette instance contient.
Cela signifie qu'il est également possible d'énumérer tous les éléments et éléments que cette instance contient.
Chaque classe qui implémente l'interface System.Collection.IEnumerable implémente également la méthode GetEnumerator qui ne prend aucun argument et renvoie une instance System.Collections.IEnumerator.
Les instances de l'interface System.Collections.IEnumerator se comportent de manière très similaire aux itérateurs C ++.
Lorsque la classe d'une instance implémente l'interface System.Collection.ICollection, alors, en termes simples, nous pouvons dire que cette instance est une collection de choses.
La version générique de cette interface, à savoir System.Collection.Generic.ICollection, est plus informative car cette interface générique indique explicitement quel est le type des éléments de la collection.
Tout cela est raisonnable, rationnel, logique et il est logique que l'interface System.Collections.ICollection hérite de l'interface System.Collections.IEnumerable, car théoriquement chaque collection est également à la fois énumérable et itérable et il est théoriquement possible de parcourir tous les éléments et éléments dans chaque collection.
L'interface System.Collections.ICollection représente une collection dynamique finie modifiable, ce qui signifie que les éléments existants peuvent être supprimés de la collection et que de nouveaux éléments peuvent être ajoutés à la même collection.
Cela explique pourquoi l'interface System.Collections.ICollection a les méthodes "Ajouter" et "Supprimer".
Étant donné que les instances de l'interface System.Collections.ICollection sont des collections finies, le mot "fini" implique que chaque collection de cette interface contient toujours un nombre fini d'éléments et d'éléments.
L'interface Count de System.Collections.ICollection de propriété suppose de renvoyer ce nombre.
L'interface System.Collections.IEnumerable n'a pas ces méthodes et propriétés que l'interface System.Collections.ICollection possède, car cela n'a aucun sens que System.Collections.IEnumerable aura ces méthodes et propriétés que l'interface System.Collections.ICollection possède.
La logique dit également que chaque instance à la fois énumérable et itérable n'est pas nécessairement une collection et pas nécessairement modifiable.
Quand je dis modifiable, je veux dire que vous ne pensez pas immédiatement que vous pouvez ajouter ou supprimer quelque chose à la fois énumérable et itérable.
Si je viens de créer une séquence finie de nombres premiers, par exemple, cette séquence finie de nombres premiers est en effet une instance de l'interface System.Collections.IEnumerable, car maintenant je peux parcourir tous les nombres premiers de cette séquence finie dans une seule boucle et faire tout ce que je veux faire avec chacun d'eux, comme imprimer chacun d'eux dans la fenêtre ou l'écran de la console, mais cette séquence finie de nombres premiers n'est pas une instance de l'interface System.Collections.ICollection, car cela n'a pas de sens pour ajouter des nombres composites à cette séquence finie de nombres premiers.
De plus, vous voulez que dans la prochaine itération, le premier nombre supérieur le plus proche soit le nombre premier actuel dans l'itération actuelle, si c'est le cas, vous ne voulez pas non plus supprimer les nombres premiers existants de cette séquence finie de nombres premiers.
Vous souhaitez également probablement utiliser, coder et écrire "yield return" dans la méthode GetEnumerator de l'interface System.Collections.IEnumerable pour produire les nombres premiers et ne rien allouer sur le tas de mémoire, puis charger le Garbage Collector (GC) à la fois désallouer et libérer cette mémoire du tas, car cela est évidemment à la fois un gaspillage de mémoire du système d'exploitation et une diminution des performances.
L'allocation de mémoire dynamique et la désallocation sur le tas doivent être effectuées lors de l'appel des méthodes et des propriétés de l'interface System.Collections.ICollection, mais pas lors de l'appel des méthodes et des propriétés de l'interface System.Collections.IEnumerable (bien que l'interface System.Collections.IEnumerable n'ait que 1 méthode et 0 propriétés).
Selon ce que d'autres ont dit dans cette page Web Stack Overflow, l'interface System.Collections.IList représente simplement une collection commandable et cela explique pourquoi les méthodes de l'interface System.Collections.IList fonctionnent avec des index contrairement à celles de l'interface System.Collections.ICollection.
En bref, l'interface System.Collections.ICollection n'implique pas qu'une instance de celle-ci peut être commandée, mais l'interface System.Collections.IList implique cela.
L'ensemble théoriquement ordonné est un cas spécial d'ensemble non ordonné.
Cela a également du sens et explique pourquoi l'interface System.Collections.IList hérite de l'interface System.Collections.ICollection.
la source