惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

宝玉的分享
宝玉的分享
NISL@THU
NISL@THU
E
Exploit-DB.com RSS Feed
L
LINUX DO - 热门话题
L
Lohrmann on Cybersecurity
K
Kaspersky official blog
Project Zero
Project Zero
Cisco Talos Blog
Cisco Talos Blog
T
The Exploit Database - CXSecurity.com
P
Palo Alto Networks Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
T
Threatpost
S
Schneier on Security
G
GRAHAM CLULEY
The Hacker News
The Hacker News
T
Threat Research - Cisco Blogs
Scott Helme
Scott Helme
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy & Cybersecurity Law Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
CERT Recently Published Vulnerability Notes
T
Tor Project blog
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
爱范儿
爱范儿
P
Privacy International News Feed
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
S
Securelist
G
Google Developers Blog
The Last Watchdog
The Last Watchdog
Google Online Security Blog
Google Online Security Blog
美团技术团队
F
Fortinet All Blogs
小众软件
小众软件
Recorded Future
Recorded Future
V
Visual Studio Blog
B
Blog RSS Feed
H
Help Net Security
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Google DeepMind News
Google DeepMind News
Blog — PlanetScale
Blog — PlanetScale
博客园 - 聂微东
Stack Overflow Blog
Stack Overflow Blog
Martin Fowler
Martin Fowler
Latest news
Latest news
Spread Privacy
Spread Privacy
H
Heimdal Security Blog

博客园 - DinoSaur

监测磁盘文件是否被修改程序 这两天随便写了个基类库 C#使用Jmail组件发送邮件 解决需求工程中的基本问题 如何编写用户操作手册 什么是软件需求 DataGrid格式 微软程序员测试题 C#中调用Windows API的要点 网站间共享数据的WebService 使用ASP.NET实现饼图 如何将一个目录里面的所有文件复制到目标目录里面。 前台对象的事件一览 剖析ASP.NET下部构造 常用的DOCUMENT.EXECCOMMAND VS.NET下web项目源代码管理 DotNet向数据库中添加图片 DataGrid应用样式文件定义动态样式 C#编码标准--编码习惯
string.Equals(string)和==的原理
DinoSaur · 2005-02-01 · via 博客园 - DinoSaur

在我写了一篇毫无价值的文章之后,经过进一步研究,补充了这部分,搞明白了为什么会出现上次的结果。最后面灰色字体是上一篇文章,有错误,仅供参考,大家只看黑色字体就可以了。

   写完了上一篇文章,我不得不接受批评。很明显,我没有读过《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 Seconds
Equals False Time: 3.391 Seconds
== False Time: 3.891 Seconds

可见当结果为true时,==Equals()快很多;当结果为false时,Equals()略快于==
结论:如果要比较的字符串相同的多,就用==;要比较的字符串中不同的多,就用Equals()