web-dev-qa-db-fra.com

Pourquoi utiliser ICollection et non IEnumerable ou List <T> dans des relations plusieurs-plusieurs / un-plusieurs?

Je le vois souvent dans les tutoriels, avec les propriétés de navigation comme ICollection<T>.

Est-ce une exigence obligatoire pour Entity Framework? Puis-je utiliser IEnumerable?

Quel est le but principal d'utiliser ICollection au lieu de IEnumerable ou même de List<T>?

330
Jan Carlo Viray

Habituellement, ce que vous choisirez dépendra 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 d'objets ne nécessitant que pour être itéré via ICollection<> (MSDN: http://msdn.Microsoft.com/en-us/library/92t2ye13.aspx ) pour obtenir une liste d'objets devant être itérés travers et modifié, List<> pour une liste d'objets devant ê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 joue avec le choix du type. Par défaut, les propriétés de navigation dans Entity Framework sont fournies avec un suivi des modifications et sont des mandataires. 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 représente le type de l'objet situé à l'autre extrémité de la relation. - Conditions requises pour la création de procurations POCOMSDN

Plus d'informations sur la définition et la gestion des relationsMSDN

410
Travis J

ICollection<T> est utilisé car l'interface IEnumerable<T> ne fournit aucun moyen d'ajouter ou de supprimer des éléments, ni de modifier la collection.

78
Justin Niessner

En réponse à votre question sur List<T>:

List<T> est une classe; spécifier une interface permet plus de flexibilité d'implémentation. Une meilleure question est "pourquoi pas IList<T>?"

Pour répondre à cette question, considérons ce que IList<T> ajoute à ICollection<T>: indexation d'entiers, ce qui signifie que les éléments ont un ordre quelconque et peuvent être récupérés par référence à cet ordre. Ce n'est probablement pas significatif dans la plupart des cas, car les articles doivent probablement être ordonnés différemment dans différents contextes.

57
phoog

Il existe quelques différences de base entre ICollection et IEnumerable

  • IEnumerable - Contient uniquement la méthode GetEnumerator pour obtenir Enumerator et créer une boucle.
  • ICollection contient les méthodes suivantes - Ajouter/Supprimer/Contient/Compte/Copier vers
  • ICollection est hérité de IEnumerable
  • Avec ICollection, vous pouvez modifier la collection en utilisant des méthodes comme ajouter/supprimer, vous n’avez pas la liberté de faire la même chose avec IEnumerable.

Programme simple:

using System;
using System.Collections;
using System.Collections.Generic;

namespace StackDemo
{
    class Program 
    {
        static void Main(string[] args)
        {
            List<Person> persons = new List<Person>();
            persons.Add(new Person("John",30));
            persons.Add(new Person("Jack", 27));

            ICollection<Person> personCollection = persons;
            IEnumerable<Person> personEnumeration = persons;

            //IEnumeration
            //IEnumration Contains only GetEnumerator method to get Enumerator and make a looping
            foreach (Person p in personEnumeration)
            {                                   
               Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);
            }

            //ICollection
            //ICollection Add/Remove/Contains/Count/CopyTo
            //ICollection is inherited from IEnumerable
            personCollection.Add(new Person("Tim", 10));

            foreach (Person p in personCollection)
            {
                Console.WriteLine("Name:{0}, Age:{1}", p.Name, p.Age);        
            }
            Console.ReadLine();

        }
    }

    class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public Person(string name,int age)
        {
            this.Name = name;
            this.Age = age;
        }
    }
}
18
Ramakrishnan

Je m'en souviens de cette façon:

  1. 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 l'instruction pour chaque énoncé en C #. IEnumerable a une propriété: Current, qui renvoie l'élément en cours.

  2. ICollection implémente IEnumerable et ajoute quelques propriétés supplémentaires dont le plus utilisé est Count. La version générique d'ICollection implémente les méthodes Add () et Remove ().

  3. IList implémente à la fois IEnumerable et ICollection et ajoute l’accès d’indexage aux éléments (ce qui n’est généralement pas nécessaire, la commande étant effectuée dans la base de données).

10
user3918295

L'idée de base d'utiliser ICollection est une interface permettant d'accéder en lecture seule à une quantité limitée de données. En fait, vous avez une propriété ICollection.Count . IEnumerable est plus approprié pour une chaîne de données où vous lisez jusqu'à un point logique, une condition explicitement spécifiée par le consommateur ou jusqu'à la fin de l'énumération.

8
Tigran

Les propriétés de navigation sont généralement définies comme virtuelles afin de pouvoir tirer parti de certaines fonctionnalités d'Entity Framework telles que le chargement différé.

Si une propriété de navigation peut contenir plusieurs entités (comme dans des 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, telles que 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-mvc-application

2
LewisAntonio803

Ce que j’ai fait par le passé, c’est de déclarer mes collections de classes internes à l’aide de IList<Class>, ICollection<Class>ou IEnumerable<Class> (si la liste est statique), selon que je devrais faire un nombre quelconque des opérations suivantes. dans une méthode de mon référentiel: énumérer, trier/ordonner ou modifier . Quand j'ai juste besoin d'énumérer (et éventuellement de trier) les objets, je crée un temp List<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 ce peut être une bonne pratique en général, idk. S'il vous plaît, corrigez-moi s'il est prouvé que cela ne serait pas une bonne pratique.

2
yardpenalty

Essayons de sortir des sentiers battus avec/par logique et comprenons clairement ces trois interfaces dans votre question:

Lorsque la classe d'une instance implémente l'interface System.Collection.IEnumerable, nous pouvons dire, en termes simples, que cette instance est à la fois énumérable et itérable, ce qui signifie que cette instance autorise d'une manière ou d'une autre à aller/obtenir/passer/traverse/parcoure tous les éléments et éléments contenus dans cette instance.

Cela signifie qu'il est également possible d'énumérer tous les éléments et éléments contenus dans cette instance.

Chaque classe qui implémente l'interface System.Collection.IEnumerable implémente également la méthode GetEnumerator qui ne prend aucun argument et retourne 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, nous pouvons dire, en termes simples, qu'il s'agit d'une collection d'éléments.

La version générique de cette interface, à savoir System.Collection.Generic.ICollection, est plus informative, car cette interface générique indique explicitement le type des éléments de la collection.

Tout cela est raisonnable, rationnel, logique et logique: l'interface System.Collections.ICollection hérite de l'interface System.Collections.IEnumerable, car en théorie chaque collection est à la fois énumérable et itérable et qu'il est théoriquement possible de passer en revue tous les éléments et éléments. dans chaque collection.

L’interface System.Collections.ICollection représente une collection dynamique finie qui sont modifiables, ce qui signifie que des éléments existants peuvent être supprimés de la collection et que de nouveaux éléments peuvent être ajoutés à la même collection.

Ceci explique pourquoi l'interface System.Collections.ICollection utilise les méthodes "Ajouter" et "Supprimer".

Etant donné que les instances de l'interface System.Collections.ICollection sont des collections finies, le mot "fini" implique que chaque collection de cette interface comporte toujours un nombre fini d'éléments et d'éléments.

La propriété Count de l'interface System.Collections.ICollection suppose de renvoyer ce nombre.

L'interface System.Collections.IEnumerable ne possède pas ces méthodes et propriétés, contrairement à l'interface System.Collections.ICollection, car cela n'a aucun sens que System.Collections.IEnumerable aura ces méthodes et propriétés de l'interface System.Collections.ICollection.

La logique dit également que chaque instance qui est à la fois énumérable et itérable ne constitue pas nécessairement une collection et n'est 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 à quelque chose qui est à 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 bien une instance de l'interface System.Collections.IEnumerable, car je peux maintenant passer en revue tous les nombres premiers de cette séquence finie en une seule boucle. et faites 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 elle n’a aucun sens. ajouter des nombres composites à cette séquence finie de nombres premiers.

Vous souhaitez également, lors de la prochaine itération, obtenir le prochain nombre premier le plus proche du nombre premier actuel, si vous ne souhaitez pas supprimer les nombres premiers existants de cette séquence finie de nombres premiers.

Aussi, vous voudrez probablement utiliser, coder et écrire "return return" dans la méthode GetEnumerator de l'interface System.Collections.IEnumerable pour produire les nombres premiers sans allouer quoi que ce soit sur le tas de mémoire, puis charger le Garbage Collector (GC) libérez et libérez cette mémoire du tas, car il s'agit évidemment d'un gaspillage de mémoire du système d'exploitation et d'une diminution des performances.

L'allocation dynamique de mémoire et l'allocation de mémoire sur le tas doivent être effectuées lors de l'appel des méthodes et propriétés de l'interface System.Collections.ICollection, mais pas lors de l'appel des méthodes et propriétés de l'interface System.Collections.IEnumerable (bien que l'interface System.Collections.IEnumerable ait uniquement 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 orderable, ce qui explique pourquoi les méthodes de l'interface System.Collections.IList fonctionnent avec des index différents de ceux de Interface System.Collections.ICollection.

En bref, l'interface System.Collections.ICollection n'implique pas qu'une instance de celle-ci est ordonnable, mais l'interface System.Collections.IList l'implique.

Jeu théoriquement ordonné est un cas spécial de jeu non ordonné.

Cela est également logique et explique pourquoi l'interface System.Collections.IList hérite de l'interface System.Collections.ICollection.

0
user11336341