列表:Count与Count()的区别

141

给定一个列表,哪种方法更好地确定其中元素的数量?

var myList = new List<string>();

myList.Count
myList.Count()

3
根据变量类型,最好使用“var”而不是“Dictionary<List<string>,int>”。这只是个人偏好。 - delete
@Randy:不确定这与问题有关;这是一种风格选择(我也偶然不同意,但这个讨论应该在另一个帖子中进行!)。 - Dan Puzey
@Randy:为什么不呢?编译器知道类型,我为什么需要写它呢?此外, 知道类型吗?是 int 吗?还是 long?这有关系吗?对于这段代码或大多数代码来说显然不重要... - Konrad Rudolph
@Randy - 正如许多人所说,这是一个偏好问题,对于我不太清楚类型的情况,使用它会更快 :) - Saxman
https://dev59.com/k3RB5IYBdhLWcg3wCjnO#8796643 - jedmao
4个回答

154

Count()是由LINQ引入的扩展方法,而Count属性是列表本身的一部分(派生自ICollection)。但在内部,LINQ会检查您的IEnumerable是否实现了ICollection,如果实现了,则使用Count属性。因此,最终使用哪一个在List上没有任何区别。

为了进一步证明我的观点,这里是Enumerable.Count()的Reflector代码:

public static int Count<TSource>(this IEnumerable<TSource> source)
{
    if (source == null)
    {
        throw Error.ArgumentNull("source");
    }
    ICollection<TSource> is2 = source as ICollection<TSource>;
    if (is2 != null)
    {
        return is2.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}

37
最终来看,除了LINQ需要一整天才能决定使用内置函数之外,其实并没有什么区别。 - Tim Schmelter
15
有一个小差别。LINQ必须检查是否实现了ICollection...因此会有一个小的(可能甚至不会被注意到)开销来进行这个检查。 - Dismissile
@BFree,我们如何在VB.NET中调用这个函数? - kbvishnu
12
从维护的角度来看,如果你的类型从 List 变成了没有 Count 属性的其他 IEnumerable,我建议使用 Count() - DLeh
2
@juanora这个回答是11年前的,所以我不能针对当时的情况进行回答。然而现在,在其中还有一个非泛型ICollection检查,如果是这种情况,则返回Count。请参见https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Count.cs#L29。数组实现ICollection,因此数组也将被包含在内。 - BFree
显示剩余2条评论

42

始终优先使用类型上的CountLength属性,而不是扩展方法Count()。 对于每个包含它们的类型,前者的时间复杂度为O(1)。 Count() 扩展方法具有一些类型检查优化,可以使其运行时间也为O(1),但如果基础集合不是它所知道的少数几种类型之一,则会降级为O(N)。


14
提醒:如果你想检查是否存在任何内容,请使用 Any() 扩展方法。 - Greg
4
@Greg,我更喜欢使用 Count > 0 而不是 Any() - Rudey
1
在 OP 的例子中(使用 List<T>),一定要使用 Count>0。如果您正在使用 IEnumerable<T>,则在大多数情况下首选 Any(),除非底层源本身很可能是 List<T>。 - Liam Laverty

14

myList.Count是列表对象上的方法,它只返回字段的值,因此非常快。由于它是一个小方法,编译器(或运行时)很可能会将其内联,然后允许编译器进行其他优化。

myList.Count()调用了一个扩展方法(由LINQ引入),它会遍历IEnumerable中的所有项,因此应该要慢得多。

但是(在Microsoft实现中),Count扩展方法对Lists进行了“特殊处理”,使其可以使用列表的Count属性,这意味着Count()方法只比Count属性慢一点点。

在大多数应用程序中,您不太可能能够区分速度差异。

所以,如果您知道正在处理的是List,请使用Count属性;否则,如果您有一个“未知”的IEnumerable,请使用Count()方法并让它为您进行优化。


2
那不准确。如果您查看Count()方法的实现,它会检查IEnumerable是否实现了ICollection,如果是,则使用Count属性。因此,归根结底,它们都是相同的。 - BFree
你能详细说明一下吗?你所说的“内置”是什么意思? - delete

7
如果您想更改集合类型,最好使用 Count() 扩展。这样,您就不必重构代码(例如使用 Length)。

使用 Count() 可以让您少担心一件事情,即使您决定使用不同类型的集合,也无需修改代码(因为.Count()可以适用于数组、列表等)。 - Don Cheadle

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