Wie erzeugt String.Equals (a, b) keine StackOverflowException?

159

Bei der Untersuchung des String ==Bedieners habe ich festgestellt, dass er anruft String.Equals(string a, string b), was bedeutet, dass es sich nur um einen Durchgang handelt.

Wenn String.Equals(string a, string b)ich die Methode untersuche, sehe ich, dass sie eine Gleichheitsprüfung mit dem ==Operator durchführt. Wie funktioniert das eigentlich und verursacht keine, StackOverflowExceptionwenn man so etwas wie "x" == "x"oder macht "x" == "y"?

Update : Ich habe JetBrains informiert und sie haben es zu einer kritischen Priorität für dotPeek gemacht. https://youtrack.jetbrains.com/issue/DOTP-6789

Ich habe auch ein Problem im GitHub-Repo von ILSpy hinzugefügt.

String-Gleichheit

Dustin Davis
quelle
Der kostenlose .NET Reflector (v6) zeigt es in C # "falsch" an (dh es wird nur angezeigt a == b), in VB.NET jedoch korrekt : a Is b.
Mark Hurd

Antworten:

217

Ihr Dekompiler hat einen Fehler. Der echte Codea == b prüft nicht , er prüft (Object)a == (Object)bund umgeht den überladenen Operator.


quelle
4
@ Arvol wahr, aber die Quelle wurde erst kürzlich veröffentlicht
Dustin Davis
2
Es ist auf jeden Fall ziemlich verschleierter Code. Ein einfaches object.ReferenceEquals(a,b)wäre viel klarer ..
Voo
1
@Voo Ich würde argumentieren, dass die aktuelle Version klarer ist. Sie nichts zu wissen brauchen , object.ReferenceEqualsmit der Gussversion (zB was , wenn aist null?), Und so lange , wie Sie wissen , was Casting ist, ist es sicherlich nicht verschleiert.
wchargin
72
"Ihr Dekompiler hat einen Fehler". Lässt das Mikrofon fallen.
Espinchi
1
@Voo Meine Vermutung: MS betrachten (Object)a == (Object)bund Object.ReferenceEquals(a, b)ungefähr gleich lesbar, aber es würde mich nicht überraschen, wenn Object.ReferenceEquals(a, b)nur eine geringe Chance besteht, nicht inline zu werden, wenn die maximale Inline-Tiefe erreicht ist. MS führt viele Mikrooptimierungen durch, da die meisten engen Schleifen im Benutzercode MS-Code aufrufen.
50

Hier ist der echte Code von Microsoft. Operator ==ist a s implementiert

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

Operatoraufrufe ==, String.Equals die implementiert sind als:

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);
}

Wie Sie sehen, wird der Vergleich für die Zeichenfolgengleichheit durchgeführt, if ((Object)a==(Object)b)indem die Zeichenfolge in umgewandelt objectund dann der Vergleich durchgeführt wird. Dadurch wird der überladene Operator ==in der Zeichenfolgenklasse nicht aufgerufen .

CriketerOnSO
quelle