При сравнении двух строк в С# для равенства, в чем разница между 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));
}
Ответ 7
Возможно http://www.siao2.com/2004/12/29/344136.aspx? (Гугл)
Ответ 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 - чрезвычайно удобная функция.