gpt4 book ai didi

C#:对于空列表,Any() 与 Count()

转载 作者:IT王子 更新时间:2023-10-29 04:17:01 25 4
gpt4 key购买 nike

A question早先发布让我思考。 Any()Count() 在空列表上使用时是否表现相似?

如解释here ,两者都应该经过 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; }

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()扩展名因为 the cast to ICollection<int> is not trivial.

无论如何,对于一个自制的空IEnumerable ,我们可以看到我们的预期,即Count()Any() 慢, 由于测试 IEnumerable 的开销是 ICollection .

完整的基准测试:

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; }
}

关于C#:对于空列表,Any() 与 Count(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16190415/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com