Как сравниваются строки в 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)) для важных сравнений, так как по умолчанию они зависят от текущей культуры системы.

Ответ 18+ 🔞

Слушай, ну вот смотри, все эти ваши сравнения строк в C# — это ж целая наука, блядь. Казалось бы, что там сравнивать? Две строки, ну сравнил и всё. Ан нет, сука, тут столько подводных камней, что просто пиздец. Регистр, культура, производительность — овердохуища нюансов.

Основные штуки, которыми ты можешь тыкать:

Метод/Оператор Что делает Когда юзать
== / != Сравнивает содержимое, а не ссылки. Но тут есть прикол — в коде он обычно использует Ordinal, но полагаться на это как на манну небесную не стоит. Для простых проверок, когда тебе похуй на культуру и нужна точная последовательность символов.
string.Equals(a, b) Статический метод, самый чёткий. Тут можно явно указать, как сравнивать. Почти всегда, особенно когда хочешь явно прописать StringComparison и не париться.
string.Compare(a, b) Возвращает циферку: меньше нуля, ноль, больше нуля. Полезно, когда надо не просто проверить равенство, а понять, какая строка "больше" для сортировки. Для сортировки или упорядочивания, когда надо знать порядок.
a.CompareTo(b) Почти то же самое, что и Compare, но вызывается от самой строки.

А теперь самое сокровенное: параметр StringComparison

Вот смотри, в чём вся соль:

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

// 1. Ordinal (часто стоит по умолчанию): Тупо сравнивает коды символов. Быстро, как угорелый, но без мозгов. Культуру не уважает.
bool isEqualOrdinal = string.Equals(str1, str2, StringComparison.Ordinal); // false — потому что 'H' и 'h' разные символы, ёпта!

// 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 — регистр игнорируется по правилам культуры.

Итак, золотые правила, чтобы не облажаться:

  • Всё, что внутри системы (ключи словарей, имена файлов, настройки, константы) — юзай StringComparison.Ordinal или OrdinalIgnoreCase. Быстро и без сюрпризов, ебать.
  • Всё, что для глаз пользователя (сортировка в интерфейсе, поиск по введённому тексту) — тогда уже CurrentCulture или InvariantCulture. Чтобы всё было культурно и по правилам языка.
  • И самое главное, запомни как "Отче наш": Никогда, блядь, просто так не вызывай методы вроде str1.Equals(str2) без указания StringComparison. Они по умолчанию смотрят на культуру системы, а это — прямой путь в ад с неочевидными багами, когда у тебя на компе одно, а на сервере другое. Я серьёзно, чувак, доверия к этому ноль ебать. Всегда указывай явно, как сравнивать.