String.Equals(a,b)为什么不会导致StackOverflowException?

160
在检查String ==操作符时,我注意到它调用了String.Equals(string a, string b)方法,这意味着它只是一个传递性操作。
检查String.Equals(string a, string b)方法后,我发现它使用==操作符进行相等性检查。那么,当执行诸如"x" == "x""x" == "y"之类的操作时,它实际上是如何工作而不会导致StackOverflowException呢?
更新:我已经告知JetBrains,并让他们将其视为dotPeek的关键任务。 https://youtrack.jetbrains.com/issue/DOTP-6789 我还在ILSpy的GitHub存储库中添加了一个问题。 String Equality

免费的.NET反编译器(v6)在C#中显示“错误”(即它只显示a == b),但在VB.NET中是正确的:a Is b - Mark Hurd
2个回答

218
你的反编译器有一个错误。真实代码 没有检查 a == b,它检查的是 (Object)a == (Object)b,从而绕过了重载运算符。

4
@Aravol 是的,但是这个资源的发布是最近的。 - Dustin Davis
2
无论如何,这是相当混淆的代码。一个简单的 object.ReferenceEquals(a,b) 会更清晰明了。 - Voo
1
@Voo 我认为当前版本更清晰。使用强制转换版本时,您不需要了解 object.ReferenceEquals 的任何内容(例如,如果 anull,会怎样?),只要您知道什么是强制转换,它肯定不会使代码变得模糊不清。 - wchargin
73
您的反编译器有一个错误。摔下话筒。 - espinchi
1
我的猜测:微软认为(Object)a == (Object)bObject.ReferenceEquals(a, b)的可读性大致相等,但如果最大内联深度已达到,Object.ReferenceEquals(a, b)有一丝不被内联的可能性,这一点也不令人惊讶。微软进行了许多微小的优化,因为用户代码中的大多数紧密循环最终会调用微软代码。 - user743382
显示剩余6条评论

50

这里是微软提供的真实代码。运算符==这样实现的

public static bool operator == (String a, String b) {
   return String.Equals(a, b);
}

运算符==调用String.Equals该方法的实现方式如下:

public static bool Equals(String a, String b) {
    if ((Object)a==(Object)b) {
        return true;
    }

    if ((Object)a==null || (Object)b==null) {
        return false;
    }

    if (a.Length != b.Length)
        return false;

    return EqualsHelper(a, b);
}

如您所见,字符串相等性的比较是通过将字符串强制转换为object并进行比较来完成的:if ((Object)a==(Object)b)。因此,这不会调用字符串类中重载的==运算符。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接