C#: Any() vs Count() for an empty list
早前的一个问题让我思考。当用于空列表时,
正如这里所解释的,这两个步骤都应该与
我用linqpad上的快速程序测试了这个问题:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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); } |
总体结果似乎表明,在这种情况下,
我不确定我是否有正确的基准,如果没有,我会感激任何修正。
编辑:我明白这在语义上会更有意义。我在问题中发布的第一个链接显示了这样一种情况,即直接使用
1 | list.Count(); |
转换为
1 | ((ICollection)list).Count; |
而
这里有一个针对4种不同情况的基准1(5)。
1 2 3 4 5 6 7 |
正如casperone在评论中所说,
不管怎样,对于自制的空的
完成基准:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | 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; } } |