Что обычно лучше всего использовать - StringComparison.OrdinalIgnoreCase или StringComparison.InvariantCultureIgnoreCase?

102

У меня есть такой код:

If key.Equals("search", StringComparison.OrdinalIgnoreCase) Then
    DoSomething()
End If

Меня не волнует случай. Должен ли я использовать OrdinalIgnoreCase, InvariantCultureIgnoreCase или CurrentCultureIgnoreCase?

  • 2
    Проверьте это действительно полезно для этой темы. Мое предложение использовать ordianlignorecase для сравнения. blogs.msdn.com/b/noahc/archive/2007/06/29/...
  • 0
    Примите во внимание ответ с высокой оценкой из сравнения повторяющихся строк: InvariantCultureIgnoreCase vs OrdinalIgnoreCase?
Показать ещё 1 комментарий
Теги:
localization

6 ответов

123
Лучший ответ

Из MSDN " Новые рекомендации по использованию строк в Microsoft.NET 2.0

Сводка. Владельцы кода, ранее использовавшие InvariantCulture для сравнения строк, обсадной колонны и сортировки, должны серьезно рассмотреть возможность использования нового набора перегрузок String в Microsoft.NET 2.0. В частности, данные, которые должны быть культурно-агностическими и лингвистически неактуальными, должны начинать указывать перегрузки с использованием элементов StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase нового перечисления StringComparison. Они обеспечивают сравнение побайтов по сравнению с strcmp, которое не только избегает ошибок от лингвистической интерпретации по существу символических строк, но и обеспечивает лучшую производительность. (15 печатных страниц)

  • 100
    Чтобы привести пример, где они различаются, рассмотрим две строки "Straße" и "STRASSE" . При использовании OrdinalIgnoreCase Equals возвращает false , тогда как InvariantCultureIgnoreCase говорит, что они равны.
  • 2
    Обновленная ссылка: docs.microsoft.com/en-us/dotnet/standard/base-types/…
45

Все зависит от

Сравнение строк unicode затруднено:

Реализация строки Unicode поиск и сравнение в тексте программное обеспечение для обработки данных должно учет наличия эквивалентного кодовые точки. В отсутствие этого, пользователи, которые ищут конкретная последовательность кодовых точек не можете найти другое визуально неразличимые глифы, которые имеют другой, но канонически эквивалентный, представление кодовой точки.

см. http://en.wikipedia.org/wiki/Unicode_equivalence


Если вы пытаетесь сравнить 2 строки Unicode в режиме без учета регистра и хотите, чтобы он работал ВЕСЬ, у вас есть невозможная проблема.

Классическим примером является Turkish i, который, когда верхний регистр становится İ (обратите внимание на точку)

По умолчанию инфраструктура .Net обычно использует CurrentCulture для связанных с строкой функций, с очень важным исключением .Equals, что использует порядковый (байтовый байт).

Это приводит, к примеру, к различным строковым функциям, которые ведут себя по-разному в зависимости от компьютерной культуры.


Тем не менее иногда нам нужна "общая цель", не чувствительная к регистру, сравнение.

Например, вы можете захотеть, чтобы сравнение строк было таким же, независимо от того, на каком компьютере установлено ваше приложение.

Для этого у нас есть 3 варианта:

  • Установить культуру в явном виде и выполнить нечувствительность к регистру с использованием правил эквивалентности unicode.
  • Установите культуру в Инвариантную Культуру и выполните сравнение без учета регистра с использованием правил эквивалентности Юникода.
  • Используйте OrdinalIgnoreCase, который будет содержать верхний регистр строки с использованием InvariantCulture, а затем выполнить сравнение байта за байтом.

Правила эквивалентности Юникода сложны, что означает использование метода 1) или 2) более дорого, чем OrdinalIgnoreCase. Тот факт, что OrdinalIgnoreCase не выполняет какую-либо специальную нормализацию в юникоде, означает, что некоторые строки, отображаемые таким же образом на экране компьютера, не будут считаться идентичными. Например: "\u0061\u030a" и "\u00e5" оба render å. Однако в порядковом сравнении будут считаться разными.

который вы выбираете, зависит от приложения, которое вы строите.

  • Если бы я писал сетевое приложение, которое использовалось только турецкими пользователями, я бы обязательно использовал метод 1.
  • Если мне просто нужен простой "поддельный" регистр без учета регистра, скажем, имя столбца в db, которое обычно является английским, я бы, вероятно, использовал метод 3.

У Microsoft есть набор рекомендаций с явными рекомендациями. Тем не менее, действительно важно понять понятие эквивалентности Юникода до подхода к этим проблемам.

Кроме того, имейте в виду, что OrdinalIgnoreCase - это особый вид зверя, который выбирает и выбирает бит порядкового сравнения с некоторые смешанные в лексикографических аспектах. Это может сбить с толку.

7

MSDN делает некоторые довольно четкие рекомендации по этому поводу: http://msdn.microsoft.com/en-us/library/ms973919.aspx

3

Я думаю, это зависит от вашей ситуации. Поскольку порядковые сравнения фактически просматривают числовые значения Unicode символов, они не будут лучшим выбором при сортировке по алфавиту. Однако для сопоставлений строк порядковый номер будет немного быстрее.

1

Это зависит от того, что вы хотите, хотя я бы уклонился от инвариантной культуры, если вы не уверены, что никогда не захотите локализовать код для других языков. Вместо этого используйте CurrentCulture.

Кроме того, OrdinalIgnoreCase должен уважать числа, которые могут быть или не быть тем, что вы хотите.

  • 1
    Вы когда-нибудь писали код VB6 в смешанной среде? Вы можете создать код, который будет компилироваться на ПК с французской локалью, но не будет компилироваться на ПК с английской локалью, потому что любые числа, хранящиеся в ресурсах формы, используют формат текущей локали. Я бы сказал, что вам нужно использовать противоположный подход: будьте очень осторожны, когда используете текущую культуру. Всегда думайте о том, будет ли ваша система работать, когда ее данные перемещаются между культурами. То же самое и с часовыми поясами.
  • 0
    Я согласен с ответом «все зависит». хотя не следите за битом "уважение чисел"?
0

Самый простой ответ: если вы не используете турецкий язык, вам не нужно использовать InvariantCulture.

См. следующую ссылку:

В С# в чем разница между ToUpper() и ToUpperInvariant()?

  • 5
    Этот ответ может быть простым, но он также очень неправильный. Турецкое «Я» является лишь примером , есть еще много возможных подводных камней.
  • 0
    Какие еще подводные камни? Я просто знаю о турецком проблемном случае.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню