我设计了以下测试:
var arrayLength=5000;
object[] objArray=new object[arrayLength];
for(var x=0;x<arrayLength;x++)
{
objArray[x]=new object();
}
objArray[4000]=null;
const int TestSize=int.MaxValue;
System.Diagnostics.Stopwatch v= new Stopwatch();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Contains(null);
}
v.Stop();
objArray.Contains(null).Dump();
v.Elapsed.ToString().Dump("Contains");
//Any ==
v.Reset();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Any(o=>o==null);
}
v.Stop();
objArray.Any(x=>x==null).Dump();
v.Elapsed.ToString().Dump("Any");
//Any Equals
v.Reset();
v.Start();
for(var x=0;x<10000;x++)
{
objArray.Any(obj=>object.Equals( obj,null));
}
v.Stop();
objArray.Any(obj=>object.Equals( obj,null)).Dump();
v.Elapsed.ToString().Dump("Any");
Run Code Online (Sandbox Code Playgroud)
null不存在时的结果:
Contains False 00:00:00.0606484Any == False 00:00:00.7532898Any object.Equals False 00:00:00.8431783当元素4000存在null时:
Contains True 00:00:00.0494515Any == True 00:00:00.5929247Any object.Equals True 00:00:00.6700742当元素10出现null时:
Contains True 00:00:00.0038035Any == True 00:00:00.0025687Any True 00:00:00.0033769所以当物体靠近前方时,Any会稍快一点; 当它在后面时,速度要慢得多.为什么?
Any将不得不为它检查的每个元素调用一个委托(一个callvirt不太可能被JIT内联的额外指令).Contains只执行该检查.这就是为什么Any慢一点.我怀疑Any看起来比包含元素的时候看起来更快的事实是基准测试不能很容易地反映它,因为它们非常接近.方法调用的设置时间是在这种情况下完成的大部分工作(而不是实际的搜索操作).
The anonymous method:
--- C:\Users\Mehrdad\AppData\Local\Temporary Projects\ConsoleApplication1\Program.cs
Console.WriteLine(s.Any(a => a == 1));
00000000 xor eax,eax
00000002 cmp ecx,1
00000005 sete al
00000008 ret
Relevant part of Enumerable.Any code:
...
00000051 mov edx,eax
00000053 mov rcx,qword ptr [rbx+8]
00000057 call qword ptr [rbx+18h] // calls the anonymous method above
0000005a movzx ecx,al
0000005d test ecx,ecx
...
Run Code Online (Sandbox Code Playgroud)