Comment String.Equals (a, b) ne produit-il pas une StackOverflowException?

159

En examinant l' String ==opérateur, j'ai remarqué qu'il appelle String.Equals(string a, string b), ce qui signifie que c'est juste un pass-through.

En examinant la String.Equals(string a, string b)méthode, je vois qu'elle effectue un contrôle d'égalité à l'aide de l' ==opérateur. Comment cela fonctionne-t-il réellement et ne cause-t-il pas une action StackOverflowExceptioncomme "x" == "x"ou "x" == "y"?

Mise à jour : j'ai informé JetBrains et ils en ont fait une priorité essentielle pour dotPeek. https://youtrack.jetbrains.com/issue/DOTP-6789

J'ai également ajouté un problème sur le dépôt GitHub d'ILSpy.

Égalité des cordes

Dustin Davis
la source
Le libre réflecteur .NET (v6) l' affiche « mauvais » en C # (il montre juste a == b), mais correct en VB.NET: a Is b.
Mark Hurd

Réponses:

217

Votre décompilateur a un bogue. Le vrai code ne vérifie pas a == b, il vérifie (Object)a == (Object)b, en contournant l'opérateur surchargé.


la source
4
@Aravol vrai, mais la source n'a été publiée que récemment
Dustin Davis
2
C'est un code assez obscur en tout cas. Un simple object.ReferenceEquals(a,b)serait beaucoup plus clair ..
Voo
1
@Voo Je dirais que la version actuelle est plus claire. Vous n'avez pas besoin de savoir quoi que ce soit sur object.ReferenceEqualsla version de la distribution (par exemple, que ase passe- nullt-il si c'est ?), Et, tant que vous savez ce qu'est la distribution, elle n'est certainement pas obscurcie.
wchargin
72
"Votre décompilateur a un bogue". Lâche le micro.
espinchi
1
@Voo Ma conjecture: MS considère (Object)a == (Object)bet à Object.ReferenceEquals(a, b)peu près tout aussi lisible, mais cela ne me surprendrait pas si Object.ReferenceEquals(a, b)juste une légère chance de ne pas être en ligne si la profondeur maximale en ligne est atteinte. MS fait beaucoup de micro-optimisations, car la plupart des boucles serrées dans le code utilisateur finissent par appeler du code MS.
50

Voici le vrai code de Microsoft. L'opérateur ==est implémenté un s

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

==appels d' opérateur String.Equals qui sont implémentés comme:

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

Comme vous le voyez, la comparaison pour l'égalité des chaînes est effectuée en utilisant le if ((Object)a==(Object)b)cast de la chaîne enobject puis en effectuant la comparaison. Donc, cela n'appellera pas l'opérateur surchargé ==dans la classe de chaînes.

CriketerOnSO
la source