当使用IEnumerable<T>时,何时应该使用.Count()和.Count呢?

10
我知道 .Count() 是在 LINQ 中的一个扩展方法,基本上它使用了 .Count。那么我想知道,在什么时候应该使用 Count(),而在什么时候应该使用 .Count.Count() 是否更适用于尚未执行枚举的可查询集合?是否始终使用 .Count() 扩展方法会更加安全,或者反过来使用属性?还是这完全取决于集合本身?
非常感谢任何建议或文章。
更新 1
在反编译 LINQ 的 .Count() 扩展方法后,发现如果 IEnumerable<T> 是一个 ICollection<T>ICollection,则它似乎使用了 .Count 属性,这也是大多数答案所建议的。现在我唯一真正看到的开销是额外的 null 和类型检查,这可能不是很大,但如果性能至关重要,它仍然可能产生一些影响。
下面是 .NET 4.0 中反编译的 LINQ .Count() 扩展方法。
public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }

    ICollection<TSource> collection = source as ICollection<TSource>;
    if (collection != null)
    {
        return collection.Count;
    }

    ICollection collection2 = source as ICollection;
    if (collection2 != null)
    {
        return collection2.Count;
    }

    int num = 0;
    checked
    {
        using (IEnumerator<TSource> enumerator = source.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                num++;
            }
        }
        return num;
    }
}
6个回答

11

扩展方法适用于任何 IEnumerable<T>,但是因为需要迭代整个序列进行计数,所以代价较高。如果序列是 ICollection<T>,也就是集合的长度是已知的,则有一种优化方式可供使用,即使用 Count 属性,但这是一种实现细节。

出于性能原因,最好使用 Count 属性。

是否应将 .Count() 主要留给尚未执行的可查询集合,因此还没有枚举?

如果您的集合是 IQueryable<T> 而不是 IEnumerable<T>,则查询提供程序可能能够以某种有效的方式返回计数。在这种情况下,您不会遭受性能损失,但这取决于查询提供程序。

IQueryable<T> 不会具有 Count 属性,因此无法在使用扩展方法和属性之间进行选择。但是,如果您的查询提供程序没有提供计算 Count() 的有效方式,则可以考虑使用 .ToList() 将集合拉到客户端。这真的取决于您打算如何使用它。


1

Count从List中检索属性(已经计算)。Count()是一种聚合,就像Sum()、Average()等。它的作用是计算可枚举项中的项目数量(如果可枚举项是列表,则我认为它在内部使用Count属性)。

这是Count()方法具体用法的示例,当它不仅仅使用Count属性时:

var list = new List {1,2,3,4,5,6,7,8,9,10};

var count = list.Where(x => x > 5).Count();

此外,Count() 还有一个重载函数可以统计满足谓词条件的项目数:
var count = list.Count(x => x > 5);

1

如果可用(即在幕后实现了ICollection<T>的对象),则同意.Count的评论。

但是他们关于.Count()是“昂贵”的说法是错误的。 Enumerable.Count()将在枚举元素并计数之前检查对象是否实现了ICollection<T>.Count

例如,像这样的东西:

public int Enumerable.Count<TSource>(IEnumerable<TSource> source)
{
    var collection = source as ICollection
    if (collection != null)
    {
        return collection.Count;
    }
}

我认为这是它内部的操作(我不确定) - Ivo
哇,我不知道我的大脑在玩什么游戏,我没有读到那部分!! - Ivo

1

当你只有一个不公开Count或Length属性的接口时,例如IEnumerabe<T>,你应该使用Count()。

如果你正在处理集合或集合接口(例如List<T>ICollection),那么你可以简单地使用Count属性,同样,如果你有一个数组,则使用Length属性。

Count()扩展属性的实现将使用底层集合的Count属性(如果可用)。否则,将枚举集合以计算计数。


0

我不确定这是否重要,因为Count()可能只是读取Count属性。性能差异真的可以忽略不计。使用任何你喜欢的。我尽可能使用Count()只是为了保持一致。


0

正如其他人所说,如果您有一个 ICollection<T>,请使用 Count 属性。

我建议 IEnumerable.Count() 方法真正适用于当您想要对枚举的元素进行计数时。相当于 SQL 中的 "SELECT COUNT(..."。

如果您还想对枚举的元素执行其他操作,生成一个集合(通常使用 ToList() 生成列表),然后您可以使用 Count 属性并执行其他任何操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接