Differenza tra InvariantCulture e confronto di stringhe ordinali
-
20-08-2019 - |
Domanda
Quando si confrontano due stringhe in c # per l'uguaglianza, qual è la differenza tra InvariantCulture e Ordinal comparation?
Soluzione
InvariantCulture
Utilizza un " standard " serie di ordini di caratteri (a, b, c, ... ecc.). Questo è in contrasto con alcuni locali specifici, che possono ordinare i caratteri in diversi ordini ('a-with-acute' potrebbe essere prima di o dopo 'a', a seconda del locale e così via).
ordinale
D'altra parte, guarda puramente i valori dei byte grezzi che rappresentano il carattere.
C'è un ottimo esempio su http://msdn.microsoft.com/en -us / library / e6883c06.aspx che mostra i risultati dei vari valori StringComparison. Alla fine, mostra (estratto):
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)
Puoi vedere quello dove produce InvariantCulture (U + 0069, U + 0049, U + 00131), Rendimenti ordinali (U + 0049, U + 0069, U + 00131).
Altri suggerimenti
Ad esempio, importa: esiste una cosa chiamata espansione dei personaggi
var s1 = "Strasse";
var s2 = "Straße";
s1.Equals(s2, StringComparison.Ordinal); //false
s1.Equals(s2, StringComparison.InvariantCulture); //true
Con InvariantCulture
& # 223; il personaggio viene espanso in ss.
Indicando Best practice per l'utilizzo delle stringhe in .NET Framework :
- Usa
StringComparison.Ordinal
oStringComparison.OrdinalIgnoreCase
per i confronti come valore predefinito sicuro per la corrispondenza di stringhe indipendenti dalla cultura. - Utilizza i confronti con
CultureInfo.InvariantCulture
oStringComparison.InvariantCulture
per prestazioni migliori. - Utilizza i valori non linguistici <=> o <=> anziché le operazioni di stringa basate su <=> quando il confronto è linguisticamente irrilevante (simbolico, ad esempio).
E infine:
- Non utilizzare le operazioni di stringa basate su <=> nella maggior parte dei casi . Una delle poche eccezioni è quando si persistono dati linguisticamente significativi ma culturalmente agnostici.
Un'altra utile differenza (in inglese in cui gli accenti non sono comuni) è che un confronto InvariantCulture confronta prima le stringhe senza distinzione tra maiuscole e minuscole, quindi, se necessario (e richiesto), distingue per caso dopo aver prima confrontato solo su lettere distinte. (Puoi anche fare un confronto senza distinzione tra maiuscole e minuscole, ovviamente, che non si distingue per caso.) Corretto: Le lettere accentate sono considerate come un altro sapore delle stesse lettere e la stringa viene confrontata per prima ignorando gli accenti e quindi contabilizzandoli se le lettere generali corrispondono tutte (come nel caso diverso tranne se non alla fine ignorate in un confronto senza distinzione tra maiuscole e minuscole). Questo raggruppa le versioni accentate della parola altrimenti identica l'una vicino all'altra invece di separarle completamente alla prima differenza di accento. Questo è il tipo di ordinamento che potresti trovare in un dizionario, con le parole in maiuscolo che appaiono accanto ai loro equivalenti minuscoli e le lettere accentate che si trovano vicino alla corrispondente lettera non accentata.
Un confronto ordinale confronta rigorosamente i valori dei caratteri numerici, fermandosi alla prima differenza. In questo modo le lettere maiuscole sono completamente separate dalle lettere minuscole (e le lettere accentate presumibilmente separate da quelle), quindi le parole in maiuscolo non si collocano da nessuna parte vicino ai loro equivalenti minuscoli.
InvariantCulture considera anche le maiuscole più grandi delle lettere minuscole, mentre Ordinale considera le maiuscole meno che minuscole (un blocco di ASCII dei vecchi tempi prima che i computer avessero lettere minuscole, le lettere maiuscole venivano allocate per prime e quindi avevano valori più bassi di le lettere minuscole aggiunte in seguito).
Ad esempio, da Ordinal: "0" < "9" < "A" < "Ab" < "Z" < "a" < "aB" < "ab" < "z" < "Á" < "Áb" < "á" < "áb"
E da InvariantCulture: "0" < "9" < "a" < "A" < "á" < "Á" < "ab" < "aB" < "Ab" < "áb" < "Áb" < "z" < "Z"
Sebbene la domanda riguardi uguaglianza , per un rapido riferimento visivo, qui l'ordine di alcune stringhe ordinate usa un paio di culture che illustrano alcune delle idiosincrasie là fuori.
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 ß ァ ぁ ア あ 亜
Osservazioni:
-
de-DE
,ja-JP
een-US
ordinano allo stesso modo -
Invariant
ordina soloss
eß
in modo diverso dalle tre culture precedenti -
da-DK
ordina in modo abbastanza diverso - la
IgnoreCase
bandiera è importante per tutte le culture campionate
Il codice utilizzato per generare la tabella sopra:
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));
}
Invariant è un tipo di confronto linguisticamente appropriato.
Ordinale è un tipo binario di confronto. (Più veloce)
Vedi http://www.siao2.com/2004/12/29/344136. aspx
Ecco un esempio in cui il confronto sull'uguaglianza delle stringhe usando InvariantCultureIgnoreCase e OrdinalIgnoreCase non darà gli stessi risultati:
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);
Se lo esegui, equals1 sarà falso e equals2 sarà vero.
Non c'è bisogno di usare fantasiosi esempi di caratteri unicode per mostrare la differenza. Ecco un semplice esempio che ho scoperto oggi che è sorprendente, costituito solo da caratteri ASCII.
Secondo la tabella ASCII, 0
(0x48) è inferiore a _
(0x95) se confrontato normalmente. InvariantCulture direbbe il contrario (codice PowerShell di seguito):
PS> [System.StringComparer]::Ordinal.Compare("_", "0")
47
PS> [System.StringComparer]::InvariantCulture.Compare("_", "0")
-1
Cerca sempre di utilizzare InvariantCulture in quei metodi stringa che lo accettano come sovraccarico. Usando InvariantCulture sei al sicuro. Molti programmatori .NET potrebbero non utilizzare questa funzionalità ma se il tuo software verrà utilizzato da culture diverse, InvariantCulture è una funzionalità estremamente utile.