Answers:
通常,您选择的内容取决于您需要使用的方法。通常,- IEnumerable<>
(MSDN:http : //msdn.microsoft.com/zh-cn/library/system.collections.ienumerable.aspx)用于仅需要迭代的对象列表ICollection<>
(MSDN:http:// msdn.microsoft.com/en-us/library/92t2ye13.aspx)以获取需要迭代和修改List<>
的对象列表,以及需要迭代,修改,排序等的对象列表(请参见此处)有关完整列表,请访问:http : //msdn.microsoft.com/en-us/library/6sh2ey19.aspx)。
从更具体的角度来看,延迟加载可以选择类型。默认情况下,实体框架中的导航属性带有更改跟踪,它们是代理。为了将动态代理创建为导航属性,虚拟类型必须实现ICollection
。
表示关系的“许多”端的导航属性必须返回实现ICollection的类型,其中T是关系另一端的对象的类型。- 创建POCO代理MSDN的要求
List
很多。尽管开销最大,但功能最多。
private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
使用与private List<int> _integers = new List<int> { 1, 2, 3 };
List<T>
有一个GetEnumerator()
方法,与其实现的方法分开IEnumerable<T>
,它返回一个可变的结构类型List<T>.Enumerator
。在大多数情况下,该类型的性能将比独立堆对象好一些。鸭式枚举器(如C#和vb.net一样)的编译器在生成foreach
代码时可以利用此优势。如果将List<T>
强制转换IEnumrable<T>
为foreach
,则该IEnumerable<T>.GetEnumerator()
方法将返回一个已分配堆的对象,从而使优化变得不可能。
ICollection<T>
之所以使用,是因为该IEnumerable<T>
界面无法提供添加项,删除项或修改集合的方式。
List<T>
实施ICollection<T>
。
ICollection
不允许任何方式添加项目,但是它仍然是一个有用的辅助,IEnumerable<T>
因为它提供的Count
成员通常比枚举所有对象快得多。请注意,如果将IList<Cat>
或ICollection<Cat>
传递给期望使用的代码IEnumerable<Animal>
,则Count()
扩展方法如果实现了非泛型ICollection
,则将很快,但如果仅实现了泛型接口,ICollection<Cat>
则不会,因为典型的将不会实现ICollection<Animal>
。
ICollection和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#中的for每个语句为我们解决了使用枚举器的大多数复杂问题。IEnumerable具有一个属性:Current,该属性返回当前元素。
ICollection实现IEnumerable,并添加了一些其他属性,其中大多数用途是Count。ICollection的通用版本实现Add()和Remove()方法。
IList同时实现IEnumerable和ICollection,并向项目添加整数索引访问(通常不需要,因为在数据库中进行排序)。
使用的基本思想ICollection
是提供一个接口,以只读方式访问一定数量的数据。实际上,您具有ICollection.Count属性。IEnumerable
更适合于您读取直到某个逻辑点,消费者明确指定的某些条件或直到枚举结束的某些数据链。
ICollection
是只读的,而ICollection<T>
不是。
导航属性通常定义为虚拟属性,以便它们可以利用某些Entity Framework功能,例如延迟加载。
如果导航属性可以容纳多个实体(如多对多或一对多关系),则其类型必须是一个列表,可以在其中添加,删除和更新条目,例如ICollection。
过去我所做的是使用或(如果是静态列表)声明我的内部类集合IList<Class>
,这取决于我是否必须在存储库中的方法中执行以下任意操作:枚举,排序/排序或修改。当我只需要枚举对象(可能是排序对象)时,我会创建一个临时模型以在IEnumerable方法中使用该集合。我认为,这种做法只有在馆藏相对较小的情况下才有效,但idk通常可能是一种好的做法。如果有证据表明这样做不好,请纠正我。ICollection<Class>
IEnumerable<Class>
List<Class>
让我们尝试通过逻辑思维开箱即用,清楚地了解问题中的这三个接口:
简单来说,当某个实例的类实现System.Collection.IEnumerable接口时,我们可以说该实例既可枚举又可迭代,这意味着该实例允许在单个循环中进行go / get / pass /遍历/遍历/遍历此实例包含的所有项目和元素。
这意味着也可以枚举此实例包含的所有项目和元素。
每个实现System.Collection.IEnumerable接口的类也都实现GetEnumerator方法,该方法不带任何参数并返回System.Collections.IEnumerator实例。
System.Collections.IEnumerator接口的实例的行为与C ++迭代器非常相似。
简单来说,当某个实例的类实现System.Collection.ICollection接口时,我们可以说该实例是事物的某种集合。
此接口的通用版本,即System.Collection.Generic.ICollection,更具信息性,因为此通用接口明确声明了集合中事物的类型。
这是所有合理,合理,逻辑的,并且使System.Collections.ICollection接口继承自System.Collections.IEnumerable接口是有意义的,因为从理论上讲每个集合都是可枚举和可迭代的,并且从理论上讲,可以遍历所有项和元素在每个集合中。
System.Collections.ICollection接口表示一个可变的有限动态集合,这意味着可以从集合中删除现有项目,并且可以将新项目添加到同一集合。
这解释了为什么System.Collections.ICollection接口具有“添加”和“删除”方法。
由于System.Collections.ICollection接口的实例是有限集合,因此单词“有限”表示该接口的每个集合中始终具有有限数量的项目和元素。
System.Collections.ICollection接口的Count属性假定返回此数字。
System.Collections.IEnumerable接口不具有System.Collections.ICollection接口具有的这些方法和属性,因为System.Collections.IEnumerable将不具有System.Collections.ICollection接口具有的这些方法和属性。
该逻辑还说,每个可枚举和可迭代的实例不一定是集合,也不一定是可更改的。
当我说“可变”时,我的意思是不要立即认为您可以在可枚举和可迭代的事物中添加或删除某些事物。
例如,如果我刚刚创建了一些质数有限序列,那么这个质数有限序列的确是System.Collections.IEnumerable接口的一个实例,因为现在我可以在一个循环中遍历此有限序列中的所有质数并执行我想对它们进行的任何操作,例如将它们打印到控制台窗口或屏幕上,但是这种有限的质数序列不是System.Collections.ICollection接口的实例,因为这对于将复数添加到此有限质数序列中。
此外,您还希望在下一次迭代中获得当前迭代中当前质数的下一个最接近的较大质数,如果是这样,您也不想从此有限质数序列中删除存在的质数。
另外,您可能还想在System.Collections.IEnumerable接口的GetEnumerator方法中使用,编写代码并编写“ yield return”,以产生质数,而不在内存堆上分配任何内容,然后将垃圾回收器(GC)分配给这两者从堆中取消分配并释放该内存,因为这显然既浪费操作系统内存,又降低了性能。
调用System.Collections.ICollection接口的方法和属性时,应在堆上进行动态内存分配和释放,但调用System.Collections.IEnumerable接口的方法和属性时,则不应这样做(尽管System.Collections.IEnumerable接口仅具有1个方法和0个属性)。
根据其他人在此Stack Overflow网页上所说的,System.Collections.IList接口只是表示一个可排序的集合,这解释了为什么System.Collections.IList接口的方法使用索引而不是System.Collections.ICollection接口的索引。
简而言之,System.Collections.ICollection接口并不意味着它的实例是可排序的,但是System.Collections.IList接口却暗示了这一点。
理论上有序集是无序集的特殊情况。
这也很有意义,并解释了为什么System.Collections.IList接口继承System.Collections.ICollection接口。
List
应该会好很多,是吗?