在对Linq IEnumerable
扩展方法进行反编译后,我很高兴看到这一点
在尝试迭代整个可枚举项之前,Count()
方法尝试将其向下转换为ICollection
或ICollection<T>
,例如:
public static int Count<TSource>(this IEnumerable<TSource> source) {
if (source == null) throw Error.ArgumentNull("source");
ICollection<TSource> collectionoft = source as ICollection<TSource>;
if (collectionoft != null) return collectionoft.Count;
ICollection collection = source as ICollection;
if (collection != null) return collection.Count;
int count = 0;
using (IEnumerator<TSource> e = source.GetEnumerator()) {
checked {
while (e.MoveNext()) count++;
}
}
return count;
}
为什么Any()
没有发生这种情况?不会因使用.Count > 0
而不是创建数组枚举器而受益吗?
答案 0 :(得分:5)
并非所有集合都为Count
属性提供O(1)访问权限。例如,ConcurrentQueue<T>
的访问计数属性是O(n)。因此优化会使情况变得更糟
不应该被称为优化。
不仅ConcurrentQueue<T>
,几乎所有并发馆藏(ConcurrentDictionary<TKey,TValue>
,ConcurrentStack<T>
等)都属于此类别
这可能是他们决定不这样做的原因。
答案 1 :(得分:0)
不。代码的成本总是比任何可能的性能提升都要大,这几乎是零。不要忘记LINQ的重点是连接一堆这样的表达式,所以你最有可能使用Any
使用谓词,或者使用它自己的束之前的过滤器等。
您使用Any
作为Count
的替代方案的情况是什么?即使Count
优化使用IMO也非常微弱 - 如果您在某些逻辑中执行Count()
期望IEnumerable
作为参数,那么您可能做错了 - 至少,你倾向于多次枚举可枚举,这很可能会破坏某些东西或者杀死你的表现:D
不要忘记,一旦你在那个可枚举的阵列上做了任何,你就会失去&#34;阵列&#34;,例如categories.Where(i => i.Name.StartsWith("Hello")).Count()
将不使用捷径。
当然,任何空的可枚举的枚举器的成本可能几乎是免费的。枚举器只是一个简单的结构,在数组上,也不会有任何昂贵的初始化。