问题描述
如果在 IEnumerable< T>
上调用了LINQ Count()
c $ c> Count 属性(例如 List< T>
), Count()
方法查找该属性并返回它(而不是通过枚举它们计数项目)?以下测试代码似乎表明它:
If the LINQ Count()
extension method is invoked on an IEnumerable<T>
that has a Count
property (e.g. List<T>
), does the Count()
method look for that property and return it (rather than counting the items by enumerating them)? The following test code seems to indicate that it does:
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 < Runs; ++i)
{
var items = Enumerable.Range(0, Items).Select(o => o.ToString()).ToList();
var list = new List<string>(items);
var enumerate = new Enumerate<string>(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<T>(IEnumerable<T> collection, Func<IEnumerable<T>, 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<T>(this IEnumerable<T> items)
{
var i = 0;
var enumerator = items.GetEnumerator();
while (enumerator.MoveNext()) i++;
return i;
}
}
// Wraps an IEnumerable<T> to hide its Count property.
public class Enumerate<T> : IEnumerable<T>
{
private readonly IEnumerable<T> collection;
public Enumerate(IEnumerable<T> collection) { this.collection = collection; }
public IEnumerator<T> GetEnumerator() { return collection.GetEnumerator(); }
IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }
}
}
strong>如何实现 IEnumerable< T>
的自定义集合暴露自己的 Count
属性, CLR Count()
扩展方法可以利用它吗?
On a related note: how can a custom collection which implements IEnumerable<T>
expose its own Count
property in such a way that the CLR Count()
extension method can take advantage of it?
推荐答案
它不是按名称查找 Count
属性,但它检查它是否实现,然后使用该类型的 code>属性。从:
It doesn't look for a Count
property by name, but it does check whether it implements ICollection<T>
, and then uses that type's Count
property. From the documentation:
(很明显,这只适用于不带谓词的重载。)
(Obviously this only applies to the overload which doesn't take a predicate.)
因此,如果您想有效地获取计数,请确保实现 ICollection< T>
。
So, if you want to obtain the count efficiently, make sure you implement ICollection<T>
.
这篇关于C#Count()扩展方法性能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!