C#Count()扩展方法性能

如果在具有Count属性的IEnumerable上调用LINQ Count()扩展方法(例如List ),则Count()方法是否查找该属性并将其返回(而不是通过枚举来计算项目)他们)? 以下测试代码似乎表明它确实:

 using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace CountSpeedTest { // Output: // List - CLR : 0 ms // Enumerate - CLR : 10 ms // List - Mine: 12 ms // Enumerate - Mine: 12 ms class Program { private const int Runs = 10; private const int Items = 1000000; static void Main(string[] args) { var total = new long[] {0, 0, 0, 0}; for (int i = 0; i  o.ToString()).ToList(); var list = new List(items); var enumerate = new Enumerate(items); total[0] += TimeCount(list, c => c.Count()); total[1] += TimeCount(enumerate, c => c.Count()); total[2] += TimeCount(list, c => c.SlowCount()); total[3] += TimeCount(enumerate, c => c.SlowCount()); } Console.WriteLine(String.Format("List - CLR : {0} ms", total[0] / Runs)); Console.WriteLine(String.Format("Enumerate - CLR : {0} ms", total[1] / Runs)); Console.WriteLine(String.Format("List - Mine: {0} ms", total[2] / Runs)); Console.WriteLine(String.Format("Enumerate - Mine: {0} ms", total[3] / Runs)); Console.ReadKey(true); } private static long TimeCount(IEnumerable collection, Func<IEnumerable, int> counter) { var stopwatch = Stopwatch.StartNew(); var count = counter(collection); stopwatch.Stop(); if (count != Items) throw new Exception("Incorrect Count"); return stopwatch.ElapsedMilliseconds; } } public static class CountExtensions { // Performs a simple enumeration based count. public static int SlowCount(this IEnumerable items) { var i = 0; var enumerator = items.GetEnumerator(); while (enumerator.MoveNext()) i++; return i; } } // Wraps an IEnumerable to hide its Count property. public class Enumerate : IEnumerable { private readonly IEnumerable collection; public Enumerate(IEnumerable collection) { this.collection = collection; } public IEnumerator GetEnumerator() { return collection.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } } 

相关说明:实现IEnumerable的自定义集合如何以CLR Count()扩展方法可以利用它的方式公开自己的Count属性?

它不会按名称查找Count属性,但会检查它是否实现ICollection ,然后使用该类型的Count属性。 从文档 :

如果源的类型实现ICollection ,则该实现用于获取元素的数量。 否则,此方法确定计数。

(显然这只适用于不带谓词的重载。)

因此,如果要有效获取计数,请确保实现ICollection

是的,Enumerable.Count方法确实会查找ICollection并使用它的Count属性(如果找到)。 您可以通过查看reflection器中的Enumerable.Count来validation这一点。

仅当您使用不带其他参数的Count扩展方法时,才会出现这种情况。 如果您使用带谓词的版本,它将遍历可枚举元素。