Как перегружен оператор == для типа string в C#

«Как перегружен оператор == для типа string в C#» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В C# оператор == для типа string перегружен (string.op_Equality). Это сравнение по значению, а не по ссылкам, что интуитивно понятнее для работы с текстом.

Как это работает

Перегруженный оператор == вызывает статический метод string.Equals(string a, string b), который сравнивает содержимое строк.

string str1 = "hello";
string str2 = "hello";
string str3 = new string(new char[] { 'h', 'e', 'l', 'l', 'o' }); // Новый объект в куче
string str4 = "HELLO";
string str5 = null;

// Сравнение значений (перегруженный ==)
Console.WriteLine(str1 == str2); // True: значения одинаковы
Console.WriteLine(str1 == str3); // True: значения одинаковы, несмотря на разные объекты
Console.WriteLine(str1 == str4); // False: регистр имеет значение
Console.WriteLine(str1 == str5); // False (str1 не null, str5 - null)
Console.WriteLine(str5 == null); // True (корректная обработка null)

// Сравнение ссылок (object.ReferenceEquals)
Console.WriteLine(ReferenceEquals(str1, str2)); // True: из-за интернирования строк
Console.WriteLine(ReferenceEquals(str1, str3)); // False: разные объекты в памяти

Ключевые особенности и лучшие практики

  1. Null-безопасность: Оператор корректно обрабатывает сравнение с null без вызова исключения NullReferenceException.
  2. Регистрозависимость: Сравнение чувствительно к регистру. Для регистронезависимого сравнения используйте:
    bool equal = string.Equals(str1, str4, StringComparison.OrdinalIgnoreCase);
    // Или
    bool equal = str1.Equals(str4, StringComparison.OrdinalIgnoreCase);
  3. Интернирование строк: Для строковых литералов (как str1 и str2) CLR использует интернирование, помещая их в пул строк. Поэтому ReferenceEquals для них тоже может возвращать true, но на это не стоит полагаться.
  4. Явное сравнение для сложных сценариев: Для сравнения с контролем культуры или типа сравнения всегда предпочтительнее использовать метод string.Equals с явным указанием StringComparison.
    // Хорошо: явное указание типа сравнения (быстрое, без учета культуры)
    bool areEqual = string.Equals(str1, str2, StringComparison.Ordinal);
  5. Отличие от object.==: Для string оператор ведет себя иначе, чем стандартный == для object. Для ссылочных типов (кроме string) == по умолчанию сравнивает ссылки, если он не перегружен.

Вывод: Перегрузка == для string — это синтаксический сахар, делающий код чище. Внутри он делегирует вызов методу string.Equals, обеспечивающему семантическое сравнение строк.