I see this a lot in tutorials, with navigation properties as ICollection<T>
.
Is this a mandatory requirement for Entity Framework? Can I use IEnumerable
?
What's the main purpose of using ICollection
instead of IEnumerable
or even List<T>
?
Usually what you choose will depend on which methods you need access to. In general - IEnumerable<>
(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx) for a list of objects that only needs to be iterated through, ICollection<>
(MSDN: http://msdn.microsoft.com/en-us/library/92t2ye13.aspx) for a list of objects that needs to be iterated through and modified, List<>
for a list of objects that needs to be iterated through, modified, sorted, etc (See here for a full list: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx).
From a more specific standpoint, lazy loading comes in to play with choosing the type. By default, navigation properties in Entity Framework come with change tracking and are proxies. In order for the dynamic proxy to be created as a navigation property, the virtual type must implement ICollection
.
A navigation property that represents the "many" end of a relationship must return a type that implements ICollection, where T is the type of the object at the other end of the relationship. -Requirements for Creating POCO ProxiesMSDN
ICollection<T>
is used because the IEnumerable<T>
interface provides no way of adding items, removing items, or otherwise modifying the collection.
Responding to your question about List<T>
:
List<T>
is a class; specifying an interface allows more flexibility of implementation. A better question is "why not IList<T>
?"
To answer that question, consider what IList<T>
adds to ICollection<T>
: integer indexing, which means the items have some arbitrary order, and can be retrieved by reference to that order. This is probably not meaningful in most cases, since items probably need to be ordered differently in different contexts.
There are some basics difference between ICollection and IEnumerable
- IEnumerable - Contains only GetEnumerator method to get Enumerator and make a looping
- ICollection is containing the following methods - Add/Remove/Contains/Count/CopyTo
- ICollection is inherited from IEnumerable
- With ICollection you can modified the collection by using the methods like add/remove , you dont have the liberty to do the same with IEnumerable.
Simple Program:
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;
}
}
}
I remember it this way:
IEnumerable has one method GetEnumerator() which allows one to read through the values in a collection but not write to it. Most of the complexity of using the enumerator is taken care of for us by the for each statement in C#. IEnumerable has one property: Current, which returns the current element.
ICollection implements IEnumerable and adds few additional properties the most use of which is Count. The generic version of ICollection implements the Add() and Remove() methods.
IList implements both IEnumerable and ICollection, and add the integer indexing access to items (which is not usually required, as ordering is done in database).
The basic idea of using ICollection
is a provide an interface to readonly-access to some finite amount of data. In fact you have a ICollection.Count property. IEnumerable
is more suitable for some chain of the data where you read till some logical point, some condition esplicitly specified by consumer or till the end of the enumeration.
Navigation properties are typically defined as virtual so that they can take advantage of certain Entity Framework functionality such as lazy loading.
If a navigation property can hold multiple entities (as in many-to-many or one-to-many relationships), its type must be a list in which entries can be added, deleted, and updated, such as ICollection.
What I have done in the past is declare my inner class collections using IList<Class>
, ICollection<Class>
or IEnumerable<Class>
(if static list) depending on whether or not I will have to do any number of the following in a method in my repository: enumerate, sort/order or modify. When I just need to enumerate (and maybe sort) over objects then I create a temp List<Class>
to work with the collection within an IEnumerable method. I think this practice would only be effective if the collection is relatively small, but it may be good practice in general, idk. Please correct me if there is evidence as to why this would not good practice.
来源:https://stackoverflow.com/questions/10113244/why-use-icollection-and-not-ienumerable-or-listt-on-many-many-one-many-relatio