为什么在多关系中使用ICollection而不是IEnumerable或List <T>?
我在教程中看到了很多,导航属性为ICollection<T>
。
这是entity framework的强制性要求吗? 我可以使用IEnumerable
吗?
使用ICollection
代替IEnumerable
甚至List<T>
的主要目的是什么?
通常你select什么取决于你需要访问哪些方法。 一般来说 – IEnumerable<>
(MSDN: http : //msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx )只需要迭代对象的列表, ICollection<>
( MSDN: http : //msdn.microsoft.com/en-us/library/92t2ye13.aspx )获取需要迭代和修改的对象列表, List<>
获取需要迭代的对象列表,修改,sorting等(见这里的完整列表: http : //msdn.microsoft.com/en-us/library/6sh2ey19.aspx )。
从更具体的angular度来看,懒惰加载来selecttypes。 默认情况下,entity framework中的导航属性带有更改跟踪,并且是代理。 为了将dynamic代理创build为导航属性,虚拟types必须实现ICollection
。
表示关系“多”端的导航属性必须返回实现ICollection的types,其中T是关系另一端的对象types。 – 创buildPOCO代理MSDN的要求
有关定义和pipe理关系的更多信息MSDN
因为IEnumerable<T>
接口不提供添加项目,删除项目或以其他方式修改集合的方法,所以使用ICollection<T>
。
回答关于List<T>
:
List<T>
是一个类; 指定一个接口允许更多的实现灵活性。 更好的问题是“为什么不要IList<T>
?
要回答这个问题,考虑一下IList<T>
加到ICollection<T>
:整数索引,这意味着这些项目有一些任意的顺序,并且可以通过参考该顺序来检索。 这在大多数情况下可能没有意义,因为项目可能需要在不同的环境下以不同的顺序排列。
使用ICollection
的基本思想是提供一个只读访问一些有限数量的数据的接口。 实际上你有一个ICollection.Count属性。 IEnumerable
更适合于读取某些逻辑点的数据链,某些情况由消费者直接指定或直到枚举结束。
ICollection和IEnumerable之间有一些基本的区别
- IEnumeration – 仅包含GetEnumerator方法来获取枚举器并进行循环
- ICollection包含以下方法 – 添加/删除/包含/计数/ CopyTo
- ICollection从IEnumerableinheritance
- 通过使用ICollection,你可以使用添加/删除(Add / Remove)等方法来修改这个集合,但是你没有这个自由去做IEnumerable。
简单程序:
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; } } }
我记得这样:
-
IEnumerable有一个方法GetEnumerator(),它允许读取集合中的值但不写入它。 使用枚举数的大部分复杂性都由C#中的每个语句来处理。 IEnumerable有一个属性:Current,它返回当前元素。
-
ICollection实现了IEnumerable,并增加了Count的最多用法。 ICollection的通用版本实现了Add()和Remove()方法。
-
IList实现IEnumerable和ICollection。
导航属性通常被定义为虚拟的,以便他们可以利用某些entity frameworkfunction,例如延迟加载。
如果导航属性可以包含多个实体(如多对多或一对多关系),则其types必须是可以添加,删除和更新条目的列表,例如ICollection。
我过去所做的是使用IList<Class>
, ICollection<Class>
或IEnumerable<Class>
(如果是静态列表)声明我的内部类集合,具体取决于是否需要在方法在我的资源库: 枚举,sorting/顺序或修改 。 当我只需要枚举(也许sorting)对象,然后创build一个临时List<Class>
以在IEnumerable方法中使用集合。 我认为这种做法只会是有效的,如果收集是比较小的,但它可能是一般的良好做法,idk。 如果有证据表明这是不好的做法,请纠正我。