Различие между инвариантными культурами и сопоставлением исходных строк

При сравнении двух строк в С# для равенства, в чем разница между InvariantCulture и сравнением ординалов?

Ответ 1

InvariantCulture

Использует "стандартный" набор порядков символов (a, b, c,... и т.д.). Это контрастирует с некоторыми конкретными локалями, которые могут сортировать символы в разных порядках ( "a-with-sharp" может быть до или после "a", в зависимости от локали и т.д.).

Порядковый

С другой стороны, он смотрит исключительно на значения исходного байта (ов), которые представляют символ.


Там отличный образец в http://msdn.microsoft.com/en-us/library/e6883c06.aspx, который показывает результаты различных значений StringComparison. В конце он показывает (выдержки):

StringComparison.InvariantCulture:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is less than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

StringComparison.Ordinal:
LATIN SMALL LETTER I (U+0069) is less than LATIN SMALL LETTER DOTLESS I (U+0131)
LATIN SMALL LETTER I (U+0069) is greater than LATIN CAPITAL LETTER I (U+0049)
LATIN SMALL LETTER DOTLESS I (U+0131) is greater than LATIN CAPITAL LETTER I (U+0049)

Вы можете видеть, что, когда InvariantCulture дает (U + 0069, U + 0049, U + 00131), Порог выхода (U + 0049, U + 0069, U + 00131).

Ответ 2

Это имеет значение, например - есть вещь, называемая расширением символов

        var s1 = "Strasse";
        var s2 = "Straße";

        s1.Equals(s2, StringComparison.Ordinal);           //false

        s1.Equals(s2, StringComparison.InvariantCulture);  //true

С InvariantCulture символ ß расширяется до ss.

Ответ 3

Указание на Рекомендации по использованию строк в .NET Framework:

  • Используйте StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase для сопоставления в качестве безопасного по умолчанию для сопоставления строк, не связанных с культурой.
  • Для повышения производительности используйте сравнения с StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase.
  • Используйте неязыковые значения StringComparison.Ordinal или StringComparison.OrdinalIgnoreCase вместо строковых операций на основе CultureInfo.InvariantCulture, если сравнение лингвистически неуместно (например, символическое).

И наконец:

  • Не используйте строковые операции на основе StringComparison.InvariantCulture в большинстве случаев. Одним из немногих исключений является то, что вы сохраняете лингвистически значимые, но культурно агностические данные.

Ответ 4

Другое удобное различие (на английском языке, где акценты являются необычными) заключается в том, что сравнение InvariantCulture сначала сравнивает целые строки с учетом регистра без учета регистра, а затем, если необходимо (и запрашивается), различается в каждом случае после первого сравнения только с отдельными буквами. (Разумеется, вы также можете провести сравнение без учета регистра, которое не будет различать в зависимости от случая.) Исправлено: Акцентированные буквы считаются еще одним ароматом одних и тех же букв и сначала сравнивается строка игнорируя акценты, а затем учитывая их, если общие буквы совпадают (как и в случае с другим случаем, за исключением того, что в конечном счете игнорируются в случае нечувствительности к регистру). Эти группы акцентируют версии одного и того же слова рядом друг с другом, а не полностью разделяются при первой разнице акцентов. Это порядок сортировки, который вы обычно находите в словаре, с заглавными словами, которые появляются рядом с их нижестоящими эквивалентами, а буквы с акцентом находятся рядом с соответствующей безударной буквой.

Сравнение ординалов строго сравнивается с числовыми значениями символов, останавливаясь при первом различии. Этот вид заглавных букв полностью отделен от букв в нижнем регистре (и буквы с акцентом, предположительно, отделенные от них), поэтому заглавные слова будут сортироваться в никуда рядом с их младшими эквивалентами.

InvariantCulture также считает, что капиталы больше, чем в нижнем регистре, тогда как Ординал считает капиталы меньше, чем нижестоящие (сохранение ASCII с предыдущих дней до того, как компьютеры имели строчные буквы, заглавные буквы были выделены первыми и, следовательно, имели более низкие значения, чем строчные буквы, добавленные позже).

Например, по ординалу: "0" < "9" "A" "Ab" < "Z" "a" "aB" "ab" "z" "& Aacute;" < "& Aacute; b" < "& Aacute;" < "& Aacute; б"

И с помощью InvariantCulture: "0" & ​​lt; "9" "a" "A" "& Aacute;" < "& Aacute;" < "ab" "aB" "Ab" < "& aacute; b" < "& Aacute; b" < "z" "Z"

Ответ 5

Инвариант - это лингвистически подходящий тип сравнения.
Ординал - это двоичный тип сравнения. (Быстрее)
См. http://www.siao2.com/2004/12/29/344136.aspx

Ответ 6

Хотя вопрос о равенстве, для быстрой визуальной ссылки, здесь порядок некоторых строк сортируется с использованием нескольких культур, иллюстрирующих некоторые из особенностей там.

Ordinal          0 9 A Ab a aB aa ab ss Ä Äb ß ä äb ぁ あ ァ ア 亜 A
IgnoreCase       0 9 a A aa ab Ab aB ss ä Ä äb Äb ß ぁ あ ァ ア 亜 A
--------------------------------------------------------------------
InvariantCulture 0 9 a A A ä Ä aa ab aB Ab äb Äb ss ß ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ß ss ァ ぁ ア あ 亜
--------------------------------------------------------------------
da-DK            0 9 a A A ab aB Ab ss ß ä Ä äb Äb aa ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ab aB ab ß ss Ä ä Äb äb aa ァ ぁ ア あ 亜
--------------------------------------------------------------------
de-DE            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
en-US            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜
--------------------------------------------------------------------
ja-JP            0 9 a A A ä Ä aa ab aB Ab äb Äb ß ss ァ ぁ ア あ 亜
IgnoreCase       0 9 A a A Ä ä aa Ab aB ab Äb äb ss ß ァ ぁ ア あ 亜

Наблюдения:

  • de-DE, ja-JP и en-US сортировать одинаково
  • Invariant сортирует только ss и ß по-разному от трех вышеупомянутых культур
  • da-DK сортируется совсем по-другому.
  • флаг IgnoreCase имеет значение для всех выбранных культур

Код, используемый для создания таблицы выше:

var l = new List<string>
    { "0", "9", "A", "Ab", "a", "aB", "aa", "ab", "ss", "ß",
      "Ä", "Äb", "ä", "äb", "あ", "ぁ", "ア", "ァ", "A", "亜" };

foreach (var comparer in new[]
{
    StringComparer.Ordinal,
    StringComparer.OrdinalIgnoreCase,
    StringComparer.InvariantCulture,
    StringComparer.InvariantCultureIgnoreCase,
    StringComparer.Create(new CultureInfo("da-DK"), false),
    StringComparer.Create(new CultureInfo("da-DK"), true),
    StringComparer.Create(new CultureInfo("de-DE"), false),
    StringComparer.Create(new CultureInfo("de-DE"), true),
    StringComparer.Create(new CultureInfo("en-US"), false),
    StringComparer.Create(new CultureInfo("en-US"), true),
    StringComparer.Create(new CultureInfo("ja-JP"), false),
    StringComparer.Create(new CultureInfo("ja-JP"), true),
})
{
    l.Sort(comparer);
    Console.WriteLine(string.Join(" ", l));
}

Ответ 8

Вот пример, где сравнение равенства строк с использованием InvariantCultureIgnoreCase и OrdinalIgnoreCase не даст одинаковых результатов:

string str = "\xC4"; //A with umlaut, Ä
string A = str.Normalize(NormalizationForm.FormC);
//Length is 1, this will contain the single A with umlaut character (Ä)
string B = str.Normalize(NormalizationForm.FormD);
//Length is 2, this will contain an uppercase A followed by an umlaut combining character
bool equals1 = A.Equals(B, StringComparison.OrdinalIgnoreCase);
bool equals2 = A.Equals(B, StringComparison.InvariantCultureIgnoreCase);

Если вы запустите это, equals1 будет false, а equals2 будет true.

Ответ 9

Не нужно использовать необычные unicode char exmaples, чтобы показать разницу. Вот один простой пример, который я обнаружил сегодня, что удивительно, состоящий только из символов ASCII.

В соответствии с таблицей ASCII 0 (0x48) при сравнении по порядку меньше, чем _ (0x95). InvariantCulture скажет обратное (код PowerShell ниже):

PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1

Ответ 10

Всегда пытайтесь использовать InvariantCulture в тех строковых методах, которые принимают его как перегрузку. Используя InvariantCulture, вы находитесь в безопасности. Многие программисты .NET могут не использовать эту функцию, но если ваше программное обеспечение будет использоваться в разных культурах, InvariantCulture - чрезвычайно удобная функция.