¿Cómo String.Equals (a, b) no produce una StackOverflowException?

159

Mientras examinaba al String ==operador, noté que llama String.Equals(string a, string b), lo que significa que es solo un paso.

Al examinar el String.Equals(string a, string b)método, veo que realiza una comprobación de igualdad utilizando el ==operador. ¿Cómo funciona esto realmente y no causa un problema StackOverflowExceptional hacer algo como "x" == "x"o "x" == "y"?

Actualización : se lo hice saber a JetBrains y lo convirtieron en una prioridad crítica para dotPeek. https://youtrack.jetbrains.com/issue/DOTP-6789

También agregué un problema en el repositorio de GitHub de ILSpy.

Cadena de igualdad

Dustin Davis
fuente
Las pantallas libres .NET Reflector (v6) es "malo" en C # (es decir, sólo muestra a == b), pero correcto en VB.NET: a Is b.
Mark Hurd

Respuestas:

217

Tu descompilador tiene un error. El código real no verifica a == b, verifica (Object)a == (Object)b, sin pasar por el operador sobrecargado.


fuente
44
@Aravol es cierto, pero la fuente se ha publicado recientemente
Dustin Davis,
2
Sin embargo, es un código bastante ofuscado en cualquier caso. Un simple object.ReferenceEquals(a,b)sería mucho más claro ..
Voo
1
@Voo Yo diría que la versión actual es más clara. No necesita saber nada acerca object.ReferenceEqualsde la versión de transmisión (por ejemplo, ¿qué apasa si es así null?) Y, siempre que sepa qué es la transmisión, ciertamente no está ofuscado.
wchargin
72
"Su descompilador tiene un error". Suelta el micrófono.
espinchi
1
@Voo Supongo: MS lo considera (Object)a == (Object)by Object.ReferenceEquals(a, b)es igualmente legible, pero no me sorprendería si Object.ReferenceEquals(a, b)solo tuviera una pequeña posibilidad de no estar en línea si se alcanza la profundidad máxima en línea. MS hace muchas micro optimizaciones, ya que la mayoría de los bucles estrechos en el código de usuario terminan llamando al código de MS.
50

Aquí está el código real de Microsoft. El operador ==se implementa a s

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

==llamadas de operador String.Equals que se implementa como:

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

Como puede ver, la comparación para la igualdad de la cadena se realiza mediante la if ((Object)a==(Object)b)conversión de la cadena objecty luego la comparación. Entonces esto no llamará al operador sobrecargado ==en la clase de cadena.

CriketerOnSO
fuente