在比较两个字符串及其变量时,我有一个想法:
string str1 = "foofoo";
string strFoo = "foo";
string str2 = strFoo + strFoo;
// Even thought str1 and str2 reference 2 different
//objects the following assertion is true.
Debug.Assert(str1 == str2);
Run Code Online (Sandbox Code Playgroud)
这纯粹是因为.NET运行时识别字符串的值是相同的,因为字符串是不可变的使得引用str2
等于str1
?
所以,当我们这样做str1 == str2
,我们其实比较参考,并不值?我原本以为这是语法糖的产物,但我是不正确的?
我写的任何不准确之处?
Dav*_*haw 14
答案在C#Spec§7.10.7中
字符串相等运算符比较字符串值而不是字符串引用.当两个单独的字符串实例包含完全相同的字符序列时,字符串的值相等,但引用不同.如§7.10.6中所述,引用类型相等运算符可用于比较字符串引用而不是字符串值.
Chr*_*ain 10
没有.
==有效,因为String类重载==运算符等效于Equals方法.
来自Reflector:
[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}
Run Code Online (Sandbox Code Playgroud)
实际上,String.Equals
首先检查它是否是相同的参考,如果没有比较内容.
如果我们看一下jitted代码,我们会看到它str2
是使用组装的String.Concat
,并且它实际上与它的引用不同str1
.我们还将看到比较是使用完成的Equals
.换句话说,断言在字符串包含相同字符时传递.
这段代码
static void Main(string[] args)
{
string str1 = "foofoo";
string strFoo = "foo";
string str2 = strFoo + strFoo;
Console.WriteLine(str1 == str2);
Debugger.Break();
}
Run Code Online (Sandbox Code Playgroud)
是否适合(请向侧面滚动以查看评论)
C:\dev\sandbox\cs-console\Program.cs @ 22:
00340070 55 push ebp
00340071 8bec mov ebp,esp
00340073 56 push esi
00340074 8b3530206003 mov esi,dword ptr ds:[3602030h] ("foofoo") <-- Note address of "foofoo"
C:\dev\sandbox\cs-console\Program.cs @ 23:
0034007a 8b0d34206003 mov ecx,dword ptr ds:[3602034h] ("foo") <-- Note different address for "foo"
C:\dev\sandbox\cs-console\Program.cs @ 24:
00340080 8bd1 mov edx,ecx
00340082 e81977fe6c call mscorlib_ni+0x2b77a0 (6d3277a0) (System.String.Concat(System.String, System.String), mdToken: 0600035f) <-- Call String.Concat to assemble str2
00340087 8bd0 mov edx,eax
00340089 8bce mov ecx,esi
0034008b e870ebfd6c call mscorlib_ni+0x2aec00 (6d31ec00) (System.String.Equals(System.String, System.String), mdToken: 060002d2) <-- Compare using String.Equals
00340090 0fb6f0 movzx esi,al
00340093 e83870f86c call mscorlib_ni+0x2570d0 (6d2c70d0) (System.Console.get_Out(), mdToken: 060008fd)
00340098 8bc8 mov ecx,eax
0034009a 8bd6 mov edx,esi
0034009c 8b01 mov eax,dword ptr [ecx]
0034009e 8b4038 mov eax,dword ptr [eax+38h]
003400a1 ff5010 call dword ptr [eax+10h]
C:\dev\sandbox\cs-console\Program.cs @ 28:
003400a4 e87775596d call mscorlib_ni+0x867620 (6d8d7620) (System.Diagnostics.Debugger.Break(), mdToken: 0600239a)
C:\dev\sandbox\cs-console\Program.cs @ 29:
>>> 003400a9 5e pop esi
003400aa 5d pop ebp
003400ab c3 ret
Run Code Online (Sandbox Code Playgroud)