ToUpperInvariant() - MSDN ошибочно по рекомендации?
В Рекомендации по использованию строк в .NET Framework, StringComparison OrdinalIgnoreCase
рекомендуется для файлов, нечувствительных к регистру файлов. (Позвольте называть это утверждение A.)
Я могу согласиться с этим, потому что я могу создать два файла в одном каталоге:
é.txt
é.txt
Их имена файлов не совпадают, второй состоит из e
и модификатора, поэтому на самом деле он имеет две буквы. (Вы можете попробовать себя с помощью copy-paste.)
Если бы имелось инвариантное сравнение культур (а не порядковое сравнение), NTFS не разрешала бы эти файлы, потому что в той же статье они объясняют, что в инвариантной культуре a + ̊ = å
Но в статье String.ToUpperInvariant()
есть другая рекомендация: (Statement B.)
Если вам нужна строчная или прописная версия идентификатора операционной системы, например имя файла, named pipe или раздел реестра, используйте методы ToLowerInvariant или ToUpperInvariant.
Мне нужно создать коллекцию путей к файлу (фактически HashSet
) для обнаружения дубликатов. Поэтому, если я буду подчиняться заявлению B при создании карты, я могу закончить с ложными срабатываниями, потому что вышеупомянутые имена файлов é.txt
и é.txt
будут считаться единичными. Правильно ли я понимаю, что утверждение B, найденное в MSDN, вводит в заблуждение? Или я что-то упускаю?
Я собираюсь создать библиотеку, желательно без известных ошибок с начала, поэтому я просто не хочу пренебрегать этим.
Обновление:
В заявлении B есть еще одна проблема: ToLowerInvariant() не может быть фактически использован. Причина (я цитирую статью "Лучшие практики" ): DO: Use ToUpperInvariant rather than ToLowerInvariant when normalizing strings for comparison.
Фактическая причина: There is a small range of characters that do not roundtrip, and going to lowercase will make these characters unavailable.
(источник)
Ответы
Ответ 1
Ни верхний, ни нижний регистр не являются правильными, если вы хотите сравнить строки для равенства без учета регистра. В обоих вариантах есть символы, которые испортили это.
Правильный способ сравнения строк без учета регистра - использовать один из нечувствительных параметров StringComparison
(вы знаете это).
Правильный способ использования структуры данных без учета регистра - использовать один из StringComparer.*IgnoreCase
. Например:
new HashSet<string>(StringComparer.InvariantCultureIgnoreCase)
Не добавляйте строчные строки перед добавлением их в структуру данных. Я бы не смог это сделать в любом обзоре кода.
Если вам нужна строчная или прописная версия идентификатора операционной системы
Вам не нужна такая вещь. Это выражение не относится к вашему делу.