TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #1219 1.36K
День девятьсот девяносто четвёртый. #ЗаметкиНаПолях
Сравнение Строк Сложнее, Чем Кажется. Начало
Сравнение строк отличается от сравнения чисел. 2 числа равны, если их значения идентичны. Для строк всё сложнее. Например, вы хотите сравнение с учетом регистра? А как насчёт разных способов написать одну и ту же букву? Например, в немецком языке часто встречается буква ß, но её также можно написать ss, так как это проще на многих клавиатурах.

В .NET есть 6 режимов сравнения строк:
1. Ordinal:
выполняет простое сравнение байтов независимо от языка. Наиболее удобен для сравнения ресурсов, чувствительных к регистру, таких как пароли.

2. OrdinalIgnoreCase: обрабатывает символы в строках для сравнения, как если бы они были преобразованы в верхний регистр с использованием соглашений инвариантного языка и региональных параметров, а затем выполняет простое сравнение байтов, которое не зависит от языка. Подходит для сравнения строк, созданных программно, когда регистр не важен, таких как пути и имена файлов.

3. InvariantCulture: сравнивает строки лингвистически релевантным способом, но он не подходит для отображения в какой-либо конкретной культуре. Основное применение - упорядочивание строк таким образом, чтобы оно было идентичным для разных культур.

4. InvariantCultureIgnoreCase: сравнивает строки лингвистически релевантным способом, игнорируя регистр.

5. CurrentCulture: может использоваться, когда строки имеют лингвистическое значение (например, отображаются для пользователя или являются результатом взаимодействия с пользователем).

6. CurrentCultureIgnoreCase: может использоваться, когда строки являются лингвистически релевантными, а их регистр - нет.

Важно явно указывать режим сравнения, чтобы избежать неожиданного поведения или, что еще хуже, проблем с безопасностью. Например, если вы сравните 2 пароля, используя текущую культуру или инвариантную культуру, пароли могут быть одинаковыми, тогда как на самом деле они могут быть разными!

Примеры
Понять разницу между Ordinal и OrdinalIgnoreCase довольно просто. Сложнее понять культурно-зависимые сравнения.
Примечание: В примерах ниже последним параметром идёт перечисление StringComparison. Для краткости я оставил лишь значение перечисления, поэтому подразумевается, что везде используется using static System.StringComparison;

// false
string.Equals("ss", "ß", OrdinalIgnoreCase);
// true в Windows / false в Linux (WSL) – об этом позже
string.Equals("ss", "ß", InvariantCulture);

\0 и ещё некоторые символы игнорируются в лингвистических сравнениях:
// false
string.Equals("a\0b", "ab", Ordinal);
// true
string.Equals("a\0b", "ab", InvariantCulture);
// true
string.Equals("a\0b", "ab", CurrentCulture);

Сравнение с учетом культуры сравнивает графемы. Например, строка A\r\nB разделена на A, \r\n и B. Это означает, что \n не является частью этой строки. Но \r или \r\n являются частью строки:
// true
"A\r\nB".Contains("\n", Ordinal);
// false
"A\r\nB".Contains("\n", InvariantCulture);
//true
"A\r\nB".Contains("\r", InvariantCulture);

Продолжение следует…

Источник:
https://www.meziantou.net/string-comparisons-are-harder-than-it-seems.htm
  • 👍 1
More from @netdeveloperdiary
  1. Oct 16, 2026День 2816. #Карьера #AI Станет ли ИИ-Кодинг Концом Программирования для Людей? Автор ориги…
  2. Oct 15, 2026Post #3374
  3. Oct 14, 2026Post #3373
  4. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 Почему существует…
  5. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  6. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →