Domanda

Quando si confrontano due stringhe in c # per l'uguaglianza, qual è la differenza tra InvariantCulture e Ordinal comparation?

È stato utile?

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 o StringComparison.OrdinalIgnoreCase per i confronti come valore predefinito sicuro per la corrispondenza di stringhe indipendenti dalla cultura.
  • Utilizza i confronti con CultureInfo.InvariantCulture o StringComparison.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 e en-US ordinano allo stesso modo
  • Invariant ordina solo ss 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.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top