簡體   English   中英

C#:Any()vs Count()表示空列表

[英]C#: Any() vs Count() for an empty list

之前發布的一個問題讓我思考。 當在空列表上使用時, Any()Count()執行是否相似?

這里所解釋的,兩者都應該經歷GetEnumerator()/MoveNext()/Dispose()的相同步驟。

我在LINQPad上使用快速程序測試了這個:

static void Main()
 {
    var list = new List<int>();

    Stopwatch stopwatch = new Stopwatch();
    stopwatch.Start();

    for (int i = 0; i < 10000; i++)
        list.Any();

    stopwatch.Stop();
    Console.WriteLine("Time elapsed for Any()   : {0}", stopwatch.Elapsed);


    stopwatch = new Stopwatch();
    stopwatch.Start();

    for (int i = 0; i < 10000; i++)
        list.Count();

    stopwatch.Stop();
    Console.WriteLine("Time elapsed for Count(): {0}", stopwatch.Elapsed);
}

一般結果似乎表明Count()在這種情況下更快。 這是為什么?

我不確定我的基准是否正確,如果不是,我會很感激。


編輯:我明白它在語義上會更有意義。 我在問題中發布的第一個鏈接顯示了一種情況,即直接使用Count()有意義的,因為將使用該值,因此問題。

Count()方法針對ICollection<T>類型進行了優化,因此不使用模式GetEnumerator()/MoveNext()/Dispose()

list.Count();

被翻譯成

((ICollection)list).Count;

Any()必須構建一個枚舉器。 所以Count()方法更快。

這里有4個不同IEnumerable實例的基准測試。 MyEmpty看起來像IEnumerable<T> MyEmpty<T>() { yield break; } IEnumerable<T> MyEmpty<T>() { yield break; }

iterations : 100000000

Function                      Any()     Count()
new List<int>()               4.310     2.252
Enumerable.Empty<int>()       3.623     6.975
new int[0]                    3.960     7.036
MyEmpty<int>()                5.631     7.194

正如casperOne在評論中所說, Enumerable.Empty<int>() is ICollection<int> ,因為它是一個數組,並且數組對Count()擴展不好,因為ICollection<int>並不簡單。

無論如何,對於一個自制的空IEnumerable ,我們可以看到我們所期望的, Count()Any()慢,因為如果IEnumerableICollection則測試的開銷。

完整基准:

class Program
{
    public const long Iterations = (long)1e8;

    static void Main()
    {
        var results = new Dictionary<string, Tuple<TimeSpan, TimeSpan>>();
        results.Add("new List<int>()", Benchmark(new List<int>(), Iterations));
        results.Add("Enumerable.Empty<int>()", Benchmark(Enumerable.Empty<int>(), Iterations));
        results.Add("new int[0]", Benchmark(new int[0], Iterations));
        results.Add("MyEmpty<int>()", Benchmark(MyEmpty<int>(), Iterations));

        Console.WriteLine("Function".PadRight(30) + "Any()".PadRight(10) + "Count()");
        foreach (var result in results)
        {
            Console.WriteLine("{0}{1}{2}", result.Key.PadRight(30), Math.Round(result.Value.Item1.TotalSeconds, 3).ToString().PadRight(10), Math.Round(result.Value.Item2.TotalSeconds, 3));
        }
        Console.ReadLine();
    }

    public static Tuple<TimeSpan, TimeSpan> Benchmark(IEnumerable<int> source, long iterations)
    {
        var anyWatch = new Stopwatch();
        anyWatch.Start();
        for (long i = 0; i < iterations; i++) source.Any();
        anyWatch.Stop();

        var countWatch = new Stopwatch();
        countWatch.Start();
        for (long i = 0; i < iterations; i++) source.Count();
        countWatch.Stop();

        return new Tuple<TimeSpan, TimeSpan>(anyWatch.Elapsed, countWatch.Elapsed);
    }

    public static IEnumerable<T> MyEmpty<T>() { yield break; }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM