Как String.Equals (a, b) не создает исключение StackOverflowException?


159

Осматривая String ==оператора, я заметил, что он звонит String.Equals(string a, string b), то есть это просто проход.

Изучая String.Equals(string a, string b)метод, я вижу, что он проверяет равенство с помощью ==оператора. Как это на самом деле работает и не вызывает, StackOverflowExceptionкогда делать что-то вроде "x" == "x"или "x" == "y"?

Обновление : я сообщил JetBrains, и они сделали это критическим приоритетом для dotPeek. https://youtrack.jetbrains.com/issue/DOTP-6789

Я также добавил проблему с репозиторием ILSpy на GitHub.

Строковое равенство


Свободные .NET Reflector (v6) показывает , что «неправильно» в C # (т.е. он просто показывает a == b), но правильно в VB.NET: a Is b.
— Марк Херд

Ответы:


217

В вашем декомпиляторе есть ошибка. Реальный код не проверяет a == b, он проверяет (Object)a == (Object)b, минуя перегруженный оператор.


4
@Aravol правда, но источник только недавно был выпущен
— Дастин Дэвис

2
В любом случае, это довольно запутанный код. Простое object.ReferenceEquals(a,b)было бы намного понятнее ..
— Воо

1
@ Во, я бы сказал, что текущая версия более понятна. Вам не нужно ничего знать о object.ReferenceEqualsкастовой версии (например, что, если aесть null?), И, пока вы знаете, что такое кастинг, он, конечно, не запутывается.
— wchargin

72
Msgstr "В вашем декомпиляторе есть ошибка". Падает микрофон
— Espinchi

1
@Voo Моё предположение: MS считает (Object)a == (Object)bи Object.ReferenceEquals(a, b)примерно одинаково читабельным, но меня не удивит, если у меня будет Object.ReferenceEquals(a, b)небольшой шанс не попасть в строку при достижении максимальной глубины. MS выполняет много микрооптимизаций, поскольку большинство циклов в пользовательском коде в конечном итоге вызывают код MS.

50

Вот реальный код от Microsoft. Оператор ==будет реализовали сек

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

Как видите, сравнение на равенство строк выполняется с использованием if ((Object)a==(Object)b)приведения строки к, objectа затем выполнения сравнения. Так что это не вызовет перегруженный оператор ==в строковом классе.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.