为什么这两个字符串比较会返回不同的结果



这里有一小段代码:

String a = "abc";
Console.WriteLine(((object)a) == ("ab" + "c")); // true 
Console.WriteLine(((object)a) == ("ab" + 'c')); // false 

为什么?

因为==正在进行引用比较。利用C#编译器;等于";在编译时已知的字符串是";分组";使

string a = "abc";
string b = "abc";

将指向相同的";abc";一串因此,他们将是平等的。

现在,("ab" + "c")在编译时被简化为"abc",而"ab" + 'c'不是,因此在引用上不相等(串联操作在运行时完成)。

请参阅此处的反编译代码

我要补充的是,Try Roslyn正在进行错误的反编译:-)甚至IlSpy:-(

它正在反编译为:

string expr_05 = "abc"
Console.WriteLine(expr_05 == "abc");
Console.WriteLine(expr_05 == "ab" + 'c');

所以字符串比较。但至少可以清楚地看到一些字符串是在编译时计算的。

为什么您的代码要进行参考比较?因为您要将两个成员中的一个强制转换为object,而将operator==强制转换为。NET不是virtual,所以它必须在编译时用编译器所拥有的信息来解决,然后。。。from==操作员

对于预定义的值类型,如果其操作数的值相等,则相等运算符(==)返回true,否则返回false对于字符串以外的引用类型,如果其两个操作数引用同一对象,则==返回true对于字符串类型,==比较字符串的值。

对于编译器来说,==运算符的第一个操作数不是string(因为您对其进行了强制转换),因此它不属于string比较。

有趣的事实:在CIL级别(.NET的汇编语言),使用的操作码是ceq,它对基元值类型进行值比较,对引用类型进行引用比较(所以最后它总是进行逐位比较,带有NaN的浮点类型除外)。它不使用";特别的";CCD_ 12方法。在这个例子中可以看到

其中

Console.WriteLine(a == ("ab" + 'c')); // True 

在对的调用中在编译时被解析

call bool [mscorlib]System.String::op_Equality(string, string)

而其他CCD_ 13只是

ceq

这就解释了为什么Roslyn反编译器在";糟糕的";(作为IlSpy:-(,请参阅错误报告)。。。它看到操作码ceq,不检查是否需要强制转换来重建正确的比较。

Holger问为什么编译器只在两个字符串文字之间添加。。。现在,以非常严格的方式阅读C#5.0规范,并将C#5.0规格视为";分离的";来自。NET规范(除了C#5.0对某些类/结构/方法/属性/…的先决条件之外),我们有:

字符串串联:

string operator +(string x, string y);
string operator +(string x, object y);
string operator +(object x, string y);

binary+运算符的这些重载执行字符串串联。如果字符串串联的操作数为null,则替换空字符串。否则,任何非字符串参数都将通过调用从类型对象继承的虚拟ToString方法转换为其字符串表示。如果ToString返回null,则替换一个空字符串。

因此,string + stringstring + nullnull + string都被精确地描述了,它们的结果可以是"0";计算的";只使用C#规范的规则。对于其他类型,必须调用virtual ToString方法。virtual ToString方法的结果没有为C#规范中的任何类型定义;假定";其结果是它会做一个错误的";事情";。例如a。NET版本的System.Boolean.ToString()返回Yes/No而不是True/False对于C#规范来说仍然可以。

地址不相同。如果要比较字符串,建议使用equals。

相关内容

  • 没有找到相关文章

最新更新