让我们想想这段代码实际上是什么样子的:
var source = new[]{ 2, 4, 6, 1, 9 }.OrderBy(x => x);
int count = source.Count();
它与
int count = Enumerable.Count(Enumerable.OrderBy(new[]{ 2, 4, 6, 1, 9 }, x => x));
的结果Enumerable.OrderBy(new[]{ 2, 4, 6, 1, 9 }, x => x)
被传递到Count
扩大。你无法避免OrderBy
执行。因此它是非流运算符,它在返回某些内容之前消耗所有源,这些内容将被传递给Count
.
因此,避免迭代所有集合的唯一方法是避免OrderBy
- 排序前对物品进行计数。
更新:您可以在任何OrderedEnumerable
- 它将使用反射来获取source
现场OrderedEnumerable<T>
它保存源序列。然后检查这个序列是否是集合,并使用Count
不执行命令:
public static class Extensions
{
public static int Count<T>(this IOrderedEnumerable<T> ordered)
{
// you can check if ordered is of type OrderedEnumerable<T>
Type type = ordered.GetType();
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
var field = type.GetField("source", flags);
var source = field.GetValue(ordered);
if (source is ICollection<T>)
return ((ICollection<T>)source).Count;
return ordered.Count();
}
}
Usage:
var source = new[]{ 2, 4, 6, 1, 9 }.OrderBy(x => x);
int count = source.Count();