Linq Count()比List.Count或Array.Length更快还是更慢?

Not*_*Dan 45 .net c# linq

LINQ Count()方法是否比List<>.Count或更快或更慢Array.Length

Jar*_*Par 61

总的来说慢一点.LINQ的计数通常是一个O(N)操作List.Count,Array.Length但都保证是O(1).

但是在某些情况下,LINQ将特殊情况下的IEnumerable<T>参数转换为某些接口类型,如IList<T>ICollection<T>.然后它将使用该Count方法进行实际Count()操作.所以它会回归到O(1).但是你仍然需要支付演员和接口调用的小额开销.


Mar*_*ell 25

Enumerable.Count()方法检查ICollection<T>,使用.Count- 所以在数组和列表的情况下,它不是更低效(只是一个额外的间接级别).


Sam*_*ron 22

马克有正确的答案,但魔鬼在细节.

在我的机器上:

  • 对于数组.Length比.Count()快约100倍
  • 对于列表.Count比.Count()快10倍 - 注意:我希望所有实现的集合的性能类似 IList<T>

由于.Length只涉及一个操作,因此数组启动速度较慢,数组上的.Count涉及一个间接层.所以.Count on arrays开始慢了10倍(在我的机器上),这可能是接口明确实现的原因之一.想象一下,如果你有一个具有两个公共属性的对象,.Count和.Length.两者都完全相同,但.Count慢了10倍.

当然,由于您必须对数组进行计数并且每秒列出数百万次才能感觉到性能受到影响,因此非实际情况确实存在很大差异.

码:

    static void TimeAction(string description, int times, Action func) {
        var watch = new Stopwatch();
        watch.Start();
        for (int i = 0; i < times; i++) {
            func();
        }
        watch.Stop();
        Console.Write(description);
        Console.WriteLine(" Time Elapsed {0} ms", watch.ElapsedMilliseconds);
    } 

    static void Main(string[] args) {
        var array = Enumerable.Range(0, 10000000).ToArray();
        var list = Enumerable.Range(0, 10000000).ToArray().ToList();

        // jit
        TimeAction("Ignore and jit", 1 ,() =>
        {
            var junk = array.Length;
            var junk2 = list.Count;
            array.Count();
            list.Count();
        });


        TimeAction("Array Length", 1000000, () => {
            var tmp1 = array.Length;
        });

        TimeAction("Array Count()", 1000000, () =>
        {
            var tmp2 = array.Count();
        });

        TimeAction("Array Length through cast", 1000000, () =>
        {
            var tmp3 = (array as ICollection<int>).Count;
        });


        TimeAction("List Count", 1000000, () =>
        {
            var tmp1 = list.Count;
        });

        TimeAction("List Count()", 1000000, () =>
        {
            var tmp2 = list.Count();
        });

        Console.ReadKey();
    }
Run Code Online (Sandbox Code Playgroud)

结果:

Array Length Time Elapsed 3 ms
Array Count() Time Elapsed 264 ms
Array Length through cast Time Elapsed 16 ms
List Count Time Elapsed 3 ms
List Count() Time Elapsed 18 ms