Що в цілому найкраще використовувати - StringComppare.OrdinalIgnoreCase або StringComppare.InvariantCultureIgnoreCase?


161

У мене такий код:

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

Мене не хвилює справа. Повинен чи я використовувати OrdinalIgnoreCase, InvariantCultureIgnoreCaseабо CurrentCultureIgnoreCase?


2
Перевірте, чи справді це корисно для цієї теми. Моя пропозиція використовувати ordianlignorecase для порівняння. blogs.msdn.com/b/noahc/archive/2007/06/29/…
UmaMaheswaran

Розглянемо відповідь з високим рівнем дублювання із дубліката порівняння рядків: InvariantCultureIgnoreCase vs OrdinalIgnoreCase?
Майкл Фрейджім

Загалом, багато що залежить від того, з якою річчю ви порівнюєте. Зокрема, якщо це вхід користувача або внутрішні речі, залежні від культури. Ви не хочете, щоб культура ПК псувала внутрішні кодові рядки порівнянь.
Nyerguds

Відповіді:


179

Нові документи .Net тепер мають таблицю, яка допоможе вам визначити, який найкраще використовувати у вашій ситуації.

З " Нових рекомендацій щодо використання рядків у Microsoft .NET 2.0 " від MSDN

Резюме: Власники коду, які раніше використовували InvariantCultureдля порівняння рядків, корпусів та сортування, повинні наполегливо розглянути можливість використання нового набору Stringперевантажень у Microsoft .NET 2.0. В Зокрема, дані , які розроблені , щоб бути культурно-агностиком і лінгвістично значення повинні починатися з зазначенням перевантажень , використовуючи або StringComparison.Ordinalабо StringComparison.OrdinalIgnoreCaseчлен нового StringComparisonперерахування. Вони забезпечують порівняння байт-байт, подібне до того, strcmpщо не лише дозволяє уникнути помилок у мовній інтерпретації по суті символічних рядків, але забезпечує кращу ефективність.


126
Щоб навести приклад, коли вони відрізняються, розглянемо два рядки "Straße"та "STRASSE". При використанні OrdinalIgnoreCaseна Equalsвіддачу false, а InvariantCultureIgnoreCaseговорить , що вони рівні.
Jeppe Stig Nielsen


64

Все залежить

Порівнювати рядки Unicode важко:

Реалізація пошукових рядків Unicode та порівнянь у програмі для обробки тексту повинна враховувати наявність еквівалентних кодів. За відсутності цієї функції користувачі, які шукають певну послідовність кодових точок, не зможуть знайти інших візуально нерозрізних гліфів, які мають інше, але канонічно еквівалентне представлення кодової точки.

дивіться: http://en.wikipedia.org/wiki/Unicode_equivalence


Якщо ви намагаєтеся порівняти 2 рядки Unicode у випадку нечутливого до справи, і хочете, щоб він працював КОЖНО , у вас є неможлива проблема.

Класичний приклад - турецький i , який у верхньому регістрі стає İ (зауважте крапку)

За замовчуванням .Net Framework зазвичай використовує CurrentCulture для функцій, пов’язаних із рядками, за дуже важливим винятком.Equals що використовує порядкове (байт за байтом) порівняння.

Це призводить, за задумом, до того, що різні струнні функції поводяться по-різному залежно від культури комп'ютера.


Тим не менш, іноді ми хочемо "загального призначення", нечутливого до випадку, порівняння.

Наприклад, ви можете хотіти, щоб ваше порівняння рядків поводилося однаково, незалежно від того, на якому комп'ютері встановлено вашу програму.

Для цього у нас є 3 варіанти:

  1. Встановіть культуру явно і виконайте порівняння з нечутливим до регістру за допомогою правил еквівалентності унікоду.
  2. Встановіть культуру "Інваріантна культура" та виконайте порівняння з невідчутними для регістру випадків, використовуючи правила еквівалентної еквівалентності.
  3. Використовуйте OrdinalIgnoreCase, який буде висувати великі регістри за допомогою InvariantCulture, а потім виконувати порівняння байтів за байтом.

Правила еквівалентності Unicode є складними, це означає, що використання методу 1) або 2) дорожче, ніж OrdinalIgnoreCase. Те, що OrdinalIgnoreCaseне виконує жодної спеціальної нормалізації унікоду, означає, що деякі рядки, які відображаються однаково на екрані комп'ютера, не вважатимуться ідентичними. Наприклад: "\u0061\u030a"і "\u00e5"обидва представляють å. Однак у порядковому порівнянні буде розглянуто інше.

Якого ви обираєте сильно, залежить від програми, яку ви будуєте.

  • Якби я писав додаток для бізнесу, який використовували лише турецькі користувачі, я б обов'язково застосував метод 1.
  • Якщо мені просто потрібне просте "підроблене" порівняння з нечутливим випадком, наприклад, ім'я стовпця в db, яке, як правило, є англійською мовою, я б, ймовірно, використовував метод 3.

Microsoft має набір рекомендацій із чіткими вказівками. Однак, дійсно важливо зрозуміти поняття еквівалентності унікоду до наближення цих проблем.

Крім того, майте на увазі, що OrdinalIgnoreCase - це особливий вид звіра, який підбирає і вибирає трохи порядкового порівняння з деякими змішаними в лексикографічному аспектах. Це може заплутати.


Що робити, якщо я будую турецьку програму, яку використовуватимуть лише турецькі користувачі, але я хочу, щоб "ayakkabı" і "ayakkabi" були рівними, чи є спосіб? Коли люди набирають на своїх телефонах, більшість із них використовують англійську клавіатуру за замовчуванням, і їм все одно, чи вводять "ı" або "i".
Волкан Сен

4

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


1

Це залежить від того, що ви хочете, хоч я б ухилявся від інваріантської культури, якщо ви не дуже впевнені , що ви ніколи не хочете , щоб локалізувати код для інших мов. Замість цього використовуйте CurrentCulture.

Також OrdinalIgnoreCase має поважати цифри, які можуть бути або не бути такими, які ви хочете.


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

Я згоден з відповіддю "це залежить". хоча не слідкуйте за бітом "поважних чисел"?
Сем Шафран

-1

Дуже проста відповідь: якщо ви не використовуєте турецьку мову, вам не потрібно використовувати InvariantCulture.

Дивіться наступне посилання:

У C # яка різниця між ToUpper () та ToUpperInvariant ()?


5
Ця відповідь може бути простою, але також дуже помилковою. Турецьке "Я" - лише приклад , можливі ще багато підводних каменів.
Охад Шнайдер

Які ще підводні камені? Я просто знаю про турецький проблемний випадок.
HelloWorld

Так, крім турецької є Азербайджан. Але це все.
Джим Балтер
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.