.NET开发
本类阅读TOP10
作者:未知 来源:月光软件站 加入时间:2005-2-28 月光软件站
在我写了一篇毫无价值的文章之后,经过进一步研究,补充了这部分,搞明白了为什么会出现上次的结果。最后面灰色字体是上一篇文章,有错误,仅供参考,大家只看黑色字体就可以了。
写完了上一篇文章,我不得不接受批评。很明显,我没有读过《Applied Microsoft .NET Framework Programming》一书,不然就不会进行这样的测试了。而且,测试方法也写得不对。经过事后研究,明白了其中的道理和本质。反思如下: 经过反编译,.NET中“==”是这样实现的:
public static bool operator ==(string a, string b)
{
return string.Equals(a, b);
}
而strings.Equals(string, string)的实现如下:
public static bool Equals(string a, string b)
if (a == b)
return true;
if ((a != null) && (b != null))
return a.Equals(b);
return false;
最后string.Equals(string)的实现(通过内部调用实现的,具体怎么实现的就不得而知了):
[MethodImpl(MethodImplOptions.InternalCall)]
public extern bool Equals(string value);
由此可见, ==先比较了两个对象的引用,如果引用相同直接返回true。如果引用不同就调用了a.Equals(b)。所以,在上面的程序中,所有"67412"都是同一个对象,==也就比Equals快了一步,没有进入string.Equals(string)就返回true了。与"67413"比较的时候,引用不同了,==通过调用string.Equals(string)才返回,所以又多用了一点比较引用的时间。如果两个字符串引用不同内容相同,那么用的时间跟上面返回false的那组测试应该是一样的。如果你以前只知道==是通过Equals实现的,现在你应该知道为什么第一组==比Equals快了。 下面是几条语句的反汇编的结果,也可以看出所有的"67412"都是来自同一个地址: string toBeTested = "67412";00000000 push ebp 00000001 mov ebp,esp 00000003 sub esp,8 00000006 push edi 00000007 push esi 00000008 push ebx 00000009 xor esi,esi 0000000b xor edi,edi 0000000d mov eax,dword ptr ds:[01AE1058h] 00000013 mov esi,eax toBeTested.Equals("67412");00000015 mov edx,dword ptr ds:[01AE1058h] 0000001b mov ecx,esi 0000001d cmp dword ptr [ecx],ecx 0000001f call dword ptr ds:[79C126F4h] 00000025 nop result = toBeTested == "67412";00000026 mov edx,dword ptr ds:[01AE1058h] 0000002c mov ecx,esi 0000002e call dword ptr ds:[79C126FCh] 00000034 movzx ebx,al 00000037 movzx eax,bl 0000003a mov edi,eax result = toBeTested.Equals("67413");0000003c mov edx,dword ptr ds:[01AE105Ch] 00000042 mov ecx,esi 00000044 cmp dword ptr [ecx],ecx 00000046 call dword ptr ds:[79C126F4h] 0000004c movzx ebx,al 0000004f movzx eax,bl 00000052 mov edi,eax result = toBeTested == "67413";00000054 mov edx,dword ptr ds:[01AE105Ch] 0000005a mov ecx,esi 0000005c call dword ptr ds:[79C126FCh] 00000062 movzx ebx,al 00000065 movzx eax,bl 00000068 mov edi,eax }0000006a nop 0000006b pop ebx 0000006c pop esi 0000006d pop edi 0000006e mov esp,ebp 00000070 pop ebp 00000071 ret
这回够彻底了吧。真相大白!还有一点没有说就是一位网友提到的“字符串池”的概念。我还不太了解,就不敢说了。 我看《Applied Microsoft .NET Framework Programming》去了……同时我也向还没有读过此书又想了解.NET原理的同志们推荐它。
附:上一篇文章的内容 要比较两个字符串是否相等,有两种方法:string toBeTested = "67412";bool result;result = toBeTested.Equals("67413");和result = toBeTested == "67413";哪一种方法好呢?测试程序: int times = 100000000; int start, end; int i; bool result; string toBeTested = "67412"; start = System.Environment.TickCount; for(i=0; i<times; i++) { result = toBeTested.Equals("67412"); } end = System.Environment.TickCount; Console.WriteLine("Equals True Time: " + (end-start)/1000.0 + " Seconds");
start = System.Environment.TickCount; for(i=0; i<times; i++) { result = toBeTested == "67412"; } end = System.Environment.TickCount; Console.WriteLine("== True Time: " + (end-start)/1000.0 + " Seconds");
start = System.Environment.TickCount; for(i=0; i<times; i++) { result = toBeTested.Equals("67413"); } end = System.Environment.TickCount; Console.WriteLine("Equals False Time: " + (end-start)/1000.0 + " Seconds");
start = System.Environment.TickCount; for(i=0; i<times; i++) { result = toBeTested == "67413"; } end = System.Environment.TickCount; Console.WriteLine("== False Time: " + (end-start)/1000.0 + " Seconds");结果:Equals True Time: 3.234 Seconds== True Time: 0.562 SecondsEquals False Time: 3.391 Seconds== False Time: 3.891 Seconds可见当结果为true时,==比Equals()快很多;当结果为false时,Equals()略快于==。结论:如果要比较的字符串相同的多,就用==;要比较的字符串中不同的多,就用Equals()。
相关软件: