IEnumerable.Count() 和 Length 到底有什么不同?

咨询区

  • balalakshmi

请问 Linq 的扩展方法 Count() 和 Length 有什么不同 ?.

回答区

  • JaredPar

Linq 中的 Count() 一般指的是 System.Linq.Enumerable 下的 Count 方法,而 Length 既不是方法也不属于 IEnumerable<T> ,它只是 Array 下的一个固定属性,比如:int[],string[]

这里的主要不同点在于性能,Length 属性的时间复杂度为 O(1),而 Count() 方法的时间复杂度则依赖于你需要操作对象的运行时类型,如果你在 ICollection<T> 上进行 Count() ,那么它的复杂度为 O(1),这是因为它会直接读取该集合的 Count 属性,如果可迭代集合没有类似直取属性那么将会迭代集合中的所有项,此时复杂度为 O(N)。

具体可参考 Count() 源代码。


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;
    }
    ICollection is3 = source as ICollection;
    if (is3 != null)
    {
        return is3.Count;
    }
    int num = 0;
    using (IEnumerator<TSource> enumerator = source.GetEnumerator())
    {
        while (enumerator.MoveNext())
        {
            num++;
        }
    }
    return num;
}

可测试案例如下:

int[] list = CreateSomeList();
Console.WriteLine(list.Length);  // O(1)
IEnumerable<int> e1 = list;
Console.WriteLine(e1.Count()); // O(1) 
IEnumerable<int> e2 = list.Where(x => x <> 42);
Console.WriteLine(e2.Count()); // O(N)

点评区

这个问题或许困扰了很多初学的朋友,JaredPar大佬解答的非常好,尤其在 Count() 源码面前了无秘密,学习了。