Porównując dwa ciągi w c # dla równości, jaka jest różnica między InvariantCulture a Ordinal porównaniem?
c#
.net
string-comparison
ordinal
Kapil
źródło
źródło
String1.Equals(String2, StringComparison.Ordinal)
, którzy używają , lepiej użyć,String1 == String2
które jestString1.Equals(String2)
samo w sobie i jest to domyślnie porównanie z rozróżnianiem wielkości liter.==
„lepszą”, ale jest to: a) krótsze, b) mniej wyraźne na temat tego, co dokładnie robi, oraz c)String1
może być zerowe bez porównaniaNullReferenceException
.StringComparison
typ. W przypadku porównania ciągów oznacza toString.Equals
.NullReferenceException
można po prostu użyć metody statycznej:String.Equals(string1, string2, StringComparison.Ordinal)
.Odpowiedzi:
InvariantCulture
Wykorzystuje „standardowy” zestaw uporządkowania znaków (a, b, c, ... itd.). Jest to sprzeczne z niektórymi konkretnymi ustawieniami regionalnymi, które mogą sortować znaki w różnych porządkach („a-z-ostrym” może występować przed lub po „a”, w zależności od ustawień regionalnych itd.).
Porządkowy
Z drugiej strony, patrzy wyłącznie na wartości surowych bajtów, które reprezentują znak.
Świetna próbka znajduje się na stronie http://msdn.microsoft.com/en-us/library/e6883c06.aspx, która pokazuje wyniki różnych wartości StringComparison. Na samym końcu pokazuje (fragment):
Widać, że tam, gdzie przynosi InvariantCulture (U + 0069, U + 0049, U + 00131), Zwykłe plony (U + 0049, U + 0069, U + 00131).
źródło
Ma to na przykład znaczenie - istnieje tzw. Ekspansja postaci
Z
InvariantCulture
ß znak zostaje rozszerzony do ss.źródło
Ordinal
iInvariantCulture
? Właśnie o to chodzi w pierwotnym pytaniu.ß
, należy zauważyć, żeß
przynajmniej w języku niemieckim jest równy podwójnemu s, Źródło: en.wikipedia.org/wiki/%C3%9Fß
iss
zamiennie w języku niemieckim (jestem native speakerem). Są przypadki, w których oba są legalne (ale często jeden jest przestarzały / niezalecany) i są przypadki, w których dozwolony jest tylko jeden formularz.Wskazując na najlepsze praktyki korzystania z ciągów w .NET Framework :
StringComparison.Ordinal
lubStringComparison.OrdinalIgnoreCase
do porównań jako bezpiecznego domyślnego dopasowania łańcucha bez względu na kulturę.StringComparison.Ordinal
lubStringComparison.OrdinalIgnoreCase
dla lepszej wydajności.StringComparison.Ordinal
lubStringComparison.OrdinalIgnoreCase
wartości zamiast operacji na łańcuchach, w oparciu o to,CultureInfo.InvariantCulture
kiedy porównanie nie ma znaczenia językowego (na przykład symboliczne).I w końcu:
StringComparison.InvariantCulture
W większości przypadków nie należy używać operacji na łańcuchach . Jednym z nielicznych wyjątków jest utrwalanie znaczących językowo, ale kulturowo agnostycznych danych.źródło
Inną przydatną różnicą (w języku angielskim, gdzie akcenty są rzadkie) jest to, że porównanie InvariantCulture porównuje najpierw wszystkie ciągi znaków bez rozróżniania wielkości liter, a następnie, jeśli to konieczne (i wymagane), rozróżnia je po pierwszym, porównując tylko poszczególne litery. (Oczywiście można również przeprowadzić porównanie bez rozróżniania wielkości liter, które nie rozróżnia wielkości liter.) Poprawiono:Litery akcentowane są uważane za inny smak tych samych liter i ciąg jest porównywany najpierw ignorując akcenty, a następnie rozliczając je, jeśli wszystkie litery ogólne pasują (podobnie jak w przypadku różnych liter, z wyjątkiem tego, że ostatecznie nie jest ignorowane w porównaniu bez rozróżniania wielkości liter). Ta grupa akcentuje wersje skądinąd tego samego słowa blisko siebie, zamiast całkowicie rozdzielić przy pierwszej różnicy akcentu. Jest to kolejność sortowania, którą zwykle można znaleźć w słowniku: słowa pisane wielkimi literami pojawiają się tuż obok ich małych odpowiedników, a litery akcentowane znajdują się w pobliżu odpowiadającej im litery nieakcentowanej.
Porównanie porządkowe porównuje ściśle wartości liczbowe, zatrzymując się na pierwszej różnicy. To sortuje wielkie litery całkowicie oddzielone od małych liter (i litery akcentowane prawdopodobnie oddzielne od tych), więc wielkie litery nie posortowałyby nigdzie w pobliżu ich małych odpowiedników.
InvariantCulture również uważa, że wielkie litery są większe niż małe litery, podczas gdy Ordinal uważa, że wielkie litery są mniejsze niż małe litery (pozostałość ASCII z dawnych czasów, zanim komputer miał małe litery, wielkie litery były przydzielane jako pierwsze, a zatem miały niższe wartości niż małe litery dodane później).
Na przykład według Ordinal:
"0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"
I przez InvariantCulture:
"0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"
źródło
Chociaż pytanie dotyczy równości , dla szybkiego wizualnego odniesienia, tutaj kolejność niektórych ciągów posortowanych za pomocą kilku kultur ilustrujących niektóre z tych dziwactw.
Obserwacje:
de-DE
,ja-JP
ien-US
posortuj w ten sam sposóbInvariant
tylko sortujess
iß
inaczej niż powyższe trzy kulturyda-DK
sortuje się zupełnie inaczejIgnoreCase
sprawy flag dla wszystkich badanych kulturKod użyty do wygenerowania powyższej tabeli:
źródło
CultureComparer
którego moglibyśmy użyć do weryfikacji. W przypadku tej tabeliDanish
kultura (informacje) okazała się bardzo ważna.)Niezmiennik jest odpowiednim językowo rodzajem porównania.
Porządek jest binarnym rodzajem porównania. (szybciej)
Patrz http://www.siao2.com/2004/12/29/344136.aspx
źródło
Oto przykład, w którym porównanie równości łańcucha przy użyciu InvariantCultureIgnoreCase i OrdinalIgnoreCase nie da takich samych wyników:
Jeśli to uruchomisz, equals1 będzie fałszywe, a equals2 będzie prawdziwe.
źródło
a="\x00e9"
(e ostre) ib="\x0065\x0301"
(e połączone z ostrym akcentem),StringComparer.Ordinal.Equals(a, b)
zwróci false, aStringComparer.InvariantCulture.Equals(a, b)
zwróci true.Nie trzeba używać fantazyjnych znaków Unicode, aby pokazać różnicę. Oto jeden prosty przykład, który odkryłem dzisiaj, który jest zaskakujący, składający się wyłącznie z znaków ASCII.
Zgodnie z tabelą ASCII
0
(0x48) jest mniejsze niż_
(0x95) w porównaniu ze zwykłym. InvariantCulture powiedziałoby coś przeciwnego (kod PowerShell poniżej):źródło
Zawsze staraj się używać InvariantCulture w tych metodach łańcuchowych, które akceptują to jako przeciążenie. Korzystając z InvariantCulture jesteś po bezpiecznej stronie. Wielu programistów .NET może nie korzystać z tej funkcji, ale jeśli twoje oprogramowanie będzie używane przez różne kultury, InvariantCulture jest niezwykle przydatną funkcją.
źródło