Как сравниваются строки в C#?

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

Ответ

Сравнение строк в C# — нетривиальная задача из-за различий в регистре, культуре и способе хранения. Важно выбирать правильный метод сравнения для конкретного сценария.

Основные методы и операторы:

Метод/Оператор Описание Рекомендуется для
== / != операторы Сравнивают содержимое строк (не ссылки). Используют StringComparison.Ordinal по умолчанию в коде, но могут зависеть от контекста. Простых сравнений, когда важна точная последовательность символов.
string.Equals(a, b) Статический метод с перегрузками для указания типа сравнения. Самый явный и рекомендуемый способ. Любых сценариев, особенно с указанием StringComparison.
string.Compare(a, b) Возвращает целое число (<0, 0, >0), указывающее на лексикографический порядок. Полезно для сортировки. Сортировки и упорядочивания строк.
a.CompareTo(b) Экземплярный метод с той же логикой, что и string.Compare.

Ключевой параметр: StringComparison

string str1 = "Hello";
string str2 = "hello";
string str3 = "HELLO";

// 1. Ordinal (по умолчанию для == в коде): Быстрое, бинарное сравнение кодов символов. Без учета культуры.
bool isEqualOrdinal = string.Equals(str1, str2, StringComparison.Ordinal); // false

// 2. OrdinalIgnoreCase: Быстрое сравнение без учета регистра. Идеально для идентификаторов, путей, URL.
bool isEqualOrdinalIgnore = string.Equals(str1, str2, StringComparison.OrdinalIgnoreCase); // true

// 3. CurrentCulture / InvariantCulture: Учитывает правила языка и региональных параметров (например, "ss" и "ß" в немецком). Медленнее.
// Используется для отображения пользователю.
bool isEqualCulture = string.Equals("straße", "strasse", StringComparison.CurrentCulture); // Может быть true в зависимости от культуры.

// 4. CurrentCultureIgnoreCase / InvariantCultureIgnoreCase
bool isEqualCultureIgnore = string.Equals(str1, str3, StringComparison.CurrentCultureIgnoreCase); // true

Правила выбора:

  • Для внутренних идентификаторов, путей, настроек, сравнения в словарях (Dictionary<string, ...>) — используйте StringComparison.Ordinal или OrdinalIgnoreCase. Это самое быстрое и безопасное.
  • Для данных, отображаемых пользователю (сортировка, поиск в UI) — используйте CurrentCulture или InvariantCulture.
  • Никогда не используйте методы без параметра StringComparison (например, str1.Equals(str2)) для важных сравнений, так как по умолчанию они зависят от текущей культуры системы.