W jaki sposób String.Equals (a, b) nie generuje wyjątku StackOverflowException?


159

Podczas badania String ==operatora zauważyłem, że wywołuje String.Equals(string a, string b), czyli jest tylko przejściem.

Po zbadaniu String.Equals(string a, string b)metody widzę, że sprawdza ona równość za pomocą ==operatora. Jak to właściwie działa i nie powoduje, StackOverflowExceptiongdy robisz coś takiego jak "x" == "x"lub "x" == "y"?

Aktualizacja : Dałem znać JetBrains i uczynili to kluczowym priorytetem dla dotPeek. https://youtrack.jetbrains.com/issue/DOTP-6789

Dodałem również problem dotyczący repozytorium GitHub firmy ILSpy.

Równość ciągów


Wolne .NET Reflector (v6) wyświetla to „źle” w języku C # (czyli to tylko pokazuje a == b), ale poprawne w VB.NET: a Is b.
Mark Hurd,

Odpowiedzi:


217

Twój dekompilator ma błąd. Prawdziwy kod nie sprawdza a == b, tylko sprawdza (Object)a == (Object)b, omijając przeciążonego operatora.


4
@Aravol prawda, ale źródło zostało opublikowane dopiero niedawno
Dustin Davis,

2
W każdym razie jest to dość zaciemniony kod. Prosty object.ReferenceEquals(a,b)byłby znacznie jaśniejszy ...
Voo

1
@Voo Twierdziłbym, że obecna wersja jest bardziej przejrzysta. Nie musisz nic wiedzieć o object.ReferenceEqualswersji obsady (np. Co jeśli ajest null?) I jeśli wiesz, czym jest casting, z pewnością nie jest ona zaciemniona.
wchargin

72
„Twój dekompilator ma błąd”. Upuszcza mikrofon.
espinchi,

1
@Voo Moje przypuszczenie: rozważ MS (Object)a == (Object)bi Object.ReferenceEquals(a, b)mniej więcej równie czytelne, ale nie zdziwiłbym się, gdyby Object.ReferenceEquals(a, b)tylko miał niewielką szansę na brak wpięcia, jeśli zostanie osiągnięta maksymalna głębokość w linii. MS wykonuje wiele mikro-optymalizacji, ponieważ większość ciasnych pętli w kodzie użytkownika kończy się wywołaniem kodu MS.

50

Oto prawdziwy kod firmy Microsoft. Operator ==jest zaimplementowany jako s

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

==wywołania operatorskie String.Equals realizowane jako:

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

Jak widać, porównanie równości łańcuchów jest wykonywane za pomocą if ((Object)a==(Object)b)rzutowania łańcucha na, objecta następnie wykonywania porównania. Więc to nie wywoła przeciążonego operatora ==w klasie string.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.