IEnumerable Count()和Length之间的区别

IEnumerable Count()Length之间的关键区别是什么?

通过调用计数IEnumerable<T>我假设你指的是System.Linq.Enumerable上的扩展方法CountLength不是IEnumerable<T>上的方法,而是.Net中数组types的属性,例如int[]

不同的是性能。 Length属性保证是O(1)操作。 Count扩展方法的复杂性根据对象的运行时types而有所不同。 它将试图通过Count属性转换成支持O(1)长度查找的几种types,如ICollection<T> 。 如果没有可用的,那么它将枚举所有项目并计数它们的复杂度为O(N)。

例如

 int[] list = CreateSomeList(); Console.WriteLine(list.Length); // O(1) IEnumerable<int> e1 = list; Console.WriteLine(e1.Count()); // O(1) IEnumerable<int> e2 = list.Where(x => x <> 42); Console.WriteLine(e2.Count()); // O(N) 

e2被实现为不支持O(1)计数的C#迭代器,因此Count方法必须枚举整个集合以确定它的持续时间。

Jon Skeet的评论除外。

Count()扩展方法的源代码:

.NET 3:

 public static int Count<TSource>(this IEnumerable<TSource> source) { if (source == null) { throw Error.ArgumentNull("source"); } ICollection<TSource> is2 = source as ICollection<TSource>; if (is2 != null) { return is2.Count; } int num = 0; using (IEnumerator<TSource> enumerator = source.GetEnumerator()) { while (enumerator.MoveNext()) { num++; } } return num; } 

.NET 4:

 public static int Count<TSource>(this IEnumerable<TSource> source) { if (source == null) { throw Error.ArgumentNull("source"); } ICollection<TSource> is2 = source as ICollection<TSource>; if (is2 != null) { return is2.Count; } ICollection is3 = source as ICollection; if (is3 != null) { return is3.Count; } int num = 0; using (IEnumerator<TSource> enumerator = source.GetEnumerator()) { while (enumerator.MoveNext()) { num++; } } return num; } 
  • 长度是一个固定的属性,例如一维数组或string。 所以从来没有必要的计数操作(multidimensional array的尺寸相乘的所有尺寸)。 这里的O(1)操作意味着无论有多less元素,检索时间总是相同的。 线性search(与此相反)是O(n)。

  • ICollections(例如List和List <T>)上的Count属性可以更改,因此它可以在“添加/删除”操作上进行更新,或者在“集合”更改后请求“计数”。 取决于对象的实现。

  • LINQ的Count()方法基本上迭代EVERY TIME它被调用(除了当对象是一个ICollectiontypes,那么ICollection.Count属性被请求)。

请注意,IEnumerables通常不是已经定义的对象集合(如列表,数组,哈希表等),而是链接到后台操作,只要请求(称为延迟执行),后台操作就会生成结果。

通常情况下,你有一个像LINQ语句这样的SQL(延迟执行的典型应用):

 IEnumerable<Person> deptLeaders = from p in persons join d in departments on p.ID equals d.LeaderID orderby p.LastName, p.FirstName select p; 

然后,有这样的代码:

 if (deptLeaders.Count() > 0) { ReportNumberOfDeptLeaders(deptLeaders.Count()); if (deptLeaders.Count() > 20) WarnTooManyDepartmentLeaders(deptLeaders.Count()); } 

因此,当发布太多的部门领导人的警告时,.NET通过人员四次通过,与部门负责人对照,按名称sorting,然后对结果对象进行计数。

这只有当个人和部门是预设的价值集合,而不是自己的查询。