Qual è generalmente il migliore da usare: StringComparison.OrdinalIgnoreCase o StringComparison.InvariantCultureIgnoreCase?


162

Ho un codice come questo:

If key.Equals("search", StringComparison.OrdinalIgnoreCase) Then
    DoSomething()
End If

Non mi interessa il caso. Dovrei usare OrdinalIgnoreCase, InvariantCultureIgnoreCaseo CurrentCultureIgnoreCase?


2
Controlla che sia davvero utile per questa discussione. Il mio suggerimento di utilizzare ordianlignorecase per il confronto. blogs.msdn.com/b/noahc/archive/2007/06/29/…
UmaMaheswaran

Considera la risposta molto votata dal confronto di stringhe
Michael Freidgeim,

Nel complesso, dipende molto dal tipo di cose che stai confrontando. In particolare, se si tratta di input dell'utente dipendente dalla cultura o roba interna. Non vuoi che la cultura del PC rovini i confronti della stringa di codice interna.
Nyerguds,

Risposte:


180

I documenti .Net più recenti ora hanno una tabella che ti aiuta a decidere quale è meglio usare nella tua situazione.

Da " Nuovi consigli per MSDN sull'uso delle stringhe in Microsoft .NET 2.0 " di MSDN

Riepilogo: i proprietari di codice che precedentemente utilizzavano il InvariantCultureconfronto delle stringhe, il case e l'ordinamento dovrebbero prendere in seria considerazione l'utilizzo di un nuovo set di Stringsovraccarichi in Microsoft .NET 2.0. In particolare, i dati progettati per essere indipendenti dalla cultura e irrilevanti dal punto di vista linguistico dovrebbero iniziare a specificare i sovraccarichi utilizzando i membri StringComparison.Ordinalo StringComparison.OrdinalIgnoreCasedella nuova StringComparisonenumerazione. Questi impongono un confronto byte per byte simile a strcmpquello che non solo evita i bug dall'interpretazione linguistica di stringhe essenzialmente simboliche, ma fornisce prestazioni migliori.


126
Per fare un esempio in cui differiscono, considerare le due stringhe "Straße"e "STRASSE". Quando si usano OrdinalIgnoreCasei Equalsritorni false, mentre InvariantCultureIgnoreCasedice che sono uguali.
Jeppe Stig Nielsen,


64

Tutto dipende

Confrontare le stringhe unicode è difficile:

L'implementazione di ricerche e confronti di stringhe Unicode nel software di elaborazione del testo deve tenere conto della presenza di punti di codice equivalenti. In assenza di questa funzione, gli utenti che cercano una particolare sequenza di punti di codice non sarebbero in grado di trovare altri glifi visivamente indistinguibili che hanno una rappresentazione di punti di codice diversa, ma canonicamente equivalente.

vedi: http://en.wikipedia.org/wiki/Unicode_equivalence


Se stai cercando di confrontare 2 stringhe unicode in un modo senza distinzione tra maiuscole e minuscole e vuoi che funzioni OVUNQUE , hai un problema impossibile.

L'esempio classico è il turco i , che quando viene maiuscolo diventa © (notare il punto)

Per impostazione predefinita, il framework .Net di solito utilizza CurrentCulture per funzioni correlate alle stringhe, con un'eccezione molto importante .Equalsche utilizza un confronto ordinale (byte per byte).

Ciò porta, in base alla progettazione, alle varie funzioni di stringa che si comportano in modo diverso a seconda della cultura del computer.


Tuttavia, a volte vogliamo un confronto "generico", senza distinzione tra maiuscole e minuscole.

Ad esempio, è possibile che il confronto delle stringhe si comporti allo stesso modo, indipendentemente dal computer su cui è installata l'applicazione.

Per raggiungere questo obiettivo abbiamo 3 opzioni:

  1. Imposta esplicitamente la cultura ed esegui un confronto senza distinzione tra maiuscole e minuscole utilizzando le regole di equivalenza unicode.
  2. Imposta la cultura su Cultura invariante ed esegui un confronto senza distinzione tra maiuscole e minuscole utilizzando le regole di equivalenza unicode.
  3. Utilizzare OrdinalIgnoreCase che renderà maiuscola la stringa utilizzando InvariantCulture e quindi eseguirà un confronto byte per byte.

Le regole di equivalenza Unicode sono complicate, il che significa che l'utilizzo del metodo 1) o 2) è più costoso di OrdinalIgnoreCase. Il fatto che OrdinalIgnoreCasenon esegua alcuna normalizzazione unicode speciale, significa che alcune stringhe che vengono visualizzate allo stesso modo sullo schermo di un computer, non saranno considerate identiche. Ad esempio: "\u0061\u030a"ed "\u00e5"entrambi rendono å. Tuttavia in un confronto ordinale sarà considerato diverso.

La scelta più ampia dipende dall'applicazione che si sta creando.

  • Se stavo scrivendo un'app line-of-business utilizzata solo dagli utenti turchi, sarei sicuro di utilizzare il metodo 1.
  • Se avessi solo bisogno di un semplice confronto "falso" senza distinzione tra maiuscole e minuscole, per esempio un nome di colonna in un db, che di solito è inglese, probabilmente userei il metodo 3.

Microsoft ha una serie di raccomandazioni con linee guida esplicite. Tuttavia, è davvero importante comprendere la nozione di equivalenza unicode prima di affrontare questi problemi.

Inoltre, tieni presente che OrdinalIgnoreCase è un tipo molto speciale di bestia, che sta selezionando e scegliendo un po 'di un confronto ordinale con alcuni aspetti lessicografici misti. Questo può essere fonte di confusione.


E se sto costruendo un'app turca che verrà utilizzata solo dagli utenti turchi ma voglio che "ayakkabı" e "ayakkabi" siano uguali, c'è un modo? Quando le persone digitano sui loro telefoni, la maggior parte di loro usa la tastiera inglese come predefinita e non si preoccupa se digitano "ı" o "i".
Volkan Sen

4

Immagino che dipenda dalla tua situazione. Poiché i confronti ordinali stanno effettivamente osservando i valori numerici Unicode dei caratteri, non saranno la scelta migliore quando si ordina in ordine alfabetico. Per i confronti di stringhe, tuttavia, ordinale sarebbe un po 'più veloce.


1

Dipende da ciò che si vuole, anche se mi piacerebbe rifuggire da InvariantCulture meno che non sei molto sicuro che non vorrete mai di localizzare il codice per le altre lingue. Utilizzare invece CurrentCulture.

Inoltre, OrdinalIgnoreCase dovrebbe rispettare i numeri, che possono o meno essere ciò che si desidera.


1
Hai mai scritto il codice VB6 in un ambiente in lingua mista? È possibile creare codice che viene compilato su un PC con la locale francese ma che non verrà compilato su PC con la locale inglese, poiché tutti i numeri memorizzati nelle risorse del modulo utilizzano il formato della locale corrente. Direi che devi adottare un approccio opposto: fai molta attenzione quando usi la cultura attuale. Pensa sempre se il tuo sistema funzionerà ancora quando i suoi dati si spostano tra le culture. Stessa cosa con i fusi orari.
Wim Coenen,

Sono d'accordo con la risposta "dipende". sebbene non segua il bit "rispetta i numeri"?
Sam Saffron,

-1

La risposta molto semplice è, a meno che tu non stia usando il turco, non è necessario utilizzare InvariantCulture.

Vedi il seguente link:

In C # qual è la differenza tra ToUpper () e ToUpperInvariant ()?


5
Questa risposta può essere semplice, ma è anche molto sbagliata. L'io turco è solo un esempio , ci sono molte altre insidie ​​possibili.
Ohad Schneider,

Quali altre insidie? Conosco solo il caso del problema turco.
HelloWorld,

Sì, oltre al turco c'è Azeri. Ma questo è tutto.
Jim Balter,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.