TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.78K subscribers
Post #1220 1.32K
День девятьсот девяносто пятый. #ЗаметкиНаПолях
Сравнение Строк Сложнее, Чем Кажется. Продолжение
Начало

NLS и ICU
В прошлом API глобализации .NET использовали разные базовые библиотеки на разных платформах. В Unix использовались международные компоненты для Unicode (ICU), а в Windows использовалась поддержка национальных языков (NLS). Это привело к некоторым различиям в поведении нескольких API глобализации при запуске приложений на разных платформах. В .NET 5.0 поведение среды выполнения изменилось. API глобализации теперь по умолчанию используют ICU на всех поддерживаемых платформах. Это позволяет приложениям избегать различий между платформами.

Обратите внимание, что ICU также используется в Windows. DLL-библиотеки ICU поставляются с Windows, начиная с Windows 10 версии 1703. Многие приложения уже начали использовать ICU в Windows. Таким образом, переход на использование ICU происходит повсюду, а не только в .NET.
.NET Framework 1.0-4.8: NLS в Windows
NET Core 1.0-3.1: NLS в Windows, ICU в Linux
.NET 5.0+: ICU* в Windows, ICU в Linux
* Можно принудительно использовать NLS с помощью флага System.Globalization.UseNls в файле конфигурации.

Если в версии Windows нет ICU, она автоматически возвращается к NLS. NLS и ICU в некоторых крайних случаях ведут себя по-разному (см. ниже). Кроме того, новая версия библиотеки может вносить изменения в поведение.

Обратите внимание, что переход с NLS на ICU не является критическим изменением. Изменения данных глобализации происходят даже в NLS, и поведение API не следует считать стабильным.

У методов разные режимы сравнения по умолчанию
Вы всегда должны явно указывать компаратор, поскольку значения по умолчанию в разных методах не согласованы. Например, string.IndexOf использует текущий язык и региональные параметры, тогда как string.Equals использует Ordinal. Поэтому всегда используйте перегрузку метода с StringComparison, IEqualityComparer<string> или IComparer<string>, когда это возможно:
// true, т.к. используется режим сравнения Ordinal
"A\r\nB".Contains("\n");

IndexOf по причинам, описанным выше, в .NET 5+ выдаёт -1, т.к. используется текущая культура, а до .NET 5 в результате будет 2:
"A\r\nB".IndexOf("\n"); 

Это также относится к Equals и CompareTo (и всем операторам ==, <, >, и т.п.):
// false
"encyclopædia".Equals("encyclopaedia");

A CompareTo опять же выдаёт 0 (равны) до .NET 5 и 1 в .NET 5+:
"encyclopædia".CompareTo("encyclopaedia");

Защита от неожиданного поведения
Анализаторы кода могут обнаруживать места потенциальных ошибок. Чтобы защититься от неожиданного поведения, рекомендуется включить в проекте анализаторы кода Roslyn. Они помогут пометить код, который может непреднамеренно использовать лингвистический компаратор, когда вероятнее всего подразумевался порядковый компаратор. Следующие правила должны помочь выявить эти проблемы:
- CA1307: Specify StringComparison for clarity (для ясности укажите StringComparison)
- CA1309: Use ordinal StringComparison (используйте порядковый режим сравнения)
- CA1310: Specify StringComparison for correctness (укажите StringComparison для корректности)

Эти особые правила не включены по умолчанию. Чтобы включить их и отображать любые нарушения как ошибки сборки, установите следующие свойства в файле проекта:
<PropertyGroup>
<AnalysisMode>AllEnabledByDefault</AnalysisMode>
<WarningsAsErrors>
$(WarningsAsErrors);CA1307;CA1309;CA1310
</WarningsAsErrors>
</PropertyGroup>

Источники:
-
https://www.meziantou.net/string-comparisons-are-harder-than-it-seems.htm
-
https://docs.microsoft.com/en-us/dotnet/standard/base-types/string-comparison-net-5-plus
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 →