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)
.但是你仍然需要支付演员和接口调用的小额开销.
Sam*_*ron 22
马克有正确的答案,但魔鬼在细节.
在我的机器上:
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