使用 的扩展方法时IEnumerable<T>
Count()
,数组至少比列表慢两倍。
Function Count()
List<int> 2,299
int[] 6,903
差异从何而来?
我知道两者都在调用以下Count
属性ICollection
:
如果源的类型实现了 ICollection,则该实现用于获取元素的计数。否则,此方法确定计数。
对于它返回的列表List<T>.Count
,对于数组,Array.Length
。此外,Array.Length
应该比 更快List<T>.Count
。
基准:
class Program
{
public const long Iterations = (long)1e8;
static void Main()
{
var list = new List<int>(){1};
var array = new int[1];
array[0] = 1;
var results = new Dictionary<string, TimeSpan>();
results.Add("List<int>", Benchmark(list, Iterations));
results.Add("int[]", Benchmark(array, Iterations));
Console.WriteLine("Function".PadRight(30) + "Count()");
foreach (var result in results)
{
Console.WriteLine("{0}{1}", result.Key.PadRight(30), Math.Round(result.Value.TotalSeconds, 3));
}
Console.ReadLine();
}
public static TimeSpan Benchmark(IEnumerable<int> source, long iterations)
{
var countWatch = new Stopwatch();
countWatch.Start();
for (long i = 0; i < iterations; i++) source.Count();
countWatch.Stop();
return countWatch.Elapsed;
}
}
编辑:
leppie和Knaģis的答案非常惊人,但我想补充一点。
正如乔恩斯基特所说:
实际上有两个等效的块,只是测试不同的集合接口类型,并使用它首先找到的任何一个(如果有的话)。我不知道 .NET 实现是先测试 ICollection 还是 ICollection< T > - 当然,我可以通过实现两个接口但从每个接口返回不同的计数来测试它,但这可能是矫枉过正。除了轻微的性能差异之外,表现良好的集合并不重要 - 我们想首先测试“最有可能”的接口,我相信它是通用接口。
通用的可能是最有可能发生的,但是如果你颠倒两者,即在通用之前调用非通用转换,Array.Count() 会比 List.Count() 快一点。另一方面,非通用版本的 List 速度较慢。
很高兴知道是否有人想调用Count()
1e8 迭代循环!
Function ICollection<T> Cast ICollection Cast
List 1,268 1,738
Array 5,925 1,683