Domanda

Confrontare le stringhe in C# è piuttosto semplice.In effetti ci sono diversi modi per farlo.Ne ho elencati alcuni nel blocco sottostante.Ciò che mi incuriosisce sono le differenze tra loro e quando uno dovrebbe essere usato rispetto agli altri?Uno dovrebbe essere evitato a tutti i costi?Ce ne sono altri che non ho elencato?

string testString = "Test";
string anotherString = "Another";

if (testString.CompareTo(anotherString) == 0) {}
if (testString.Equals(anotherString)) {}
if (testString == anotherString) {}

(Nota:Sto cercando l'uguaglianza in questo esempio, non inferiore o superiore a, ma sentiti libero di commentare anche questo)

È stato utile?

Soluzione

Ecco le regole su come funzionano queste funzioni:

stringValue.CompareTo(otherStringValue)

  1. null viene prima di una stringa
  2. utilizza CultureInfo.CurrentCulture.CompareInfo.Compare, il che significa che utilizzerà un confronto dipendente dalle impostazioni cultura.Questo potrebbe significare questo ß confronterà uguale a SS in Germania o simili

stringValue.Equals(otherStringValue)

  1. null non è considerato uguale a nulla
  2. a meno che non specifichi a StringComparison opzione, utilizzerà quello che sembra un controllo di uguaglianza ordinale diretto, vale a dire ß non è lo stesso di SS, in qualsiasi lingua o cultura

stringValue == otherStringValue

  1. Non è la stessa cosa di stringValue.Equals().
  2. IL == l'operatore chiama l'operatore statico Equals(string a, string b) metodo (che a sua volta va a un metodo internal EqualsHelper per fare il confronto.
  3. Chiamando .Equals() su a null la stringa ottiene null eccezione di riferimento, mentre è attivo == non.

Object.ReferenceEquals(stringValue, otherStringValue)

Controlla solo che i riferimenti siano gli stessi, ad es.non sono solo due stringhe con lo stesso contenuto, stai confrontando un oggetto stringa con se stesso.


Tieni presente che con le opzioni precedenti che utilizzano chiamate al metodo, sono presenti sovraccarichi con più opzioni per specificare come confrontare.

Il mio consiglio se vuoi solo verificare l'uguaglianza è di decidere se vuoi usare un confronto dipendente dalla cultura o meno, e poi usare .CompareTo O .Equals, a seconda della scelta.

Altri suggerimenti

Da MSDN:

"Il metodo comparativo è stato progettato principalmente per l'uso nelle operazioni di smistamento o alfabetizzazione.Non dovrebbe essere usato quando lo scopo principale della chiamata del metodo è determinare se due stringhe sono equivalenti.Per determinare se due stringhe sono equivalenti, chiamare il metodo Equals. "

Suggeriscono di usare .Equals invece di .CompareTo quando si cerca esclusivamente l’uguaglianza.Non sono sicuro che ci sia una differenza tra .Equals E == per il string classe.A volte userò .Equals O Object.ReferenceEquals invece di == per le mie lezioni nel caso in cui qualcuno arrivi in ​​un secondo momento e ridefinisca il == operatore per quella classe.

Se sei mai curioso delle differenze nei metodi BCL, Riflettore È tuo amico :-)

Seguo queste linee guida:

Corrispondenza esatta: MODIFICARE:In precedenza ho sempre utilizzato l'operatore == in base al principio che all'interno di Equals(string, string) l'operatore object == viene utilizzato per confrontare i riferimenti all'oggetto ma sembra che strA.Equals(strB) sia ancora complessivamente più veloce dell'1-11% rispetto a string. Equals(strA, strB), strA == strB e string.CompareOrdinal(strA, strB).Ho testato il loop con un cronometro su valori di stringa interni/non interni, con lunghezze di stringa uguali/diverse e dimensioni variabili (da 1B a 5 MB).

strA.Equals(strB)

Corrispondenza leggibile dall'uomo (culture occidentali, senza distinzione tra maiuscole e minuscole):

string.Compare(strA, strB, StringComparison.OrdinalIgnoreCase) == 0

Corrispondenza leggibile dall'uomo (tutte le altre culture, maiuscole/minuscole/accento/kana/ecc. definiti da CultureInfo):

string.Compare(strA, strB, myCultureInfo) == 0

Corrispondenza leggibile dall'uomo con regole personalizzate (tutte le altre culture):

CompareOptions compareOptions = CompareOptions.IgnoreCase
                              | CompareOptions.IgnoreWidth
                              | CompareOptions.IgnoreNonSpace;
string.Compare(strA, strB, CultureInfo.CurrentCulture, compareOptions) == 0

COME Ed detto, CompareTo viene utilizzato per l'ordinamento.

C'è una differenza, tuttavia, tra .Equals e ==.

== risolve a essenzialmente il seguente codice:

if(object.ReferenceEquals(left, null) && 
   object.ReferenceEquals(right, null))
    return true;
if(object.ReferenceEquals(left, null))
    return right.Equals(left);
return left.Equals(right);

Il semplice motivo è che quanto segue genererà un'eccezione:

string a = null;
string b = "foo";

bool equal = a.Equals(b);

E quanto segue non lo farà:

string a = null;
string b = "foo";

bool equal = a == b;

Buone spiegazioni e pratiche sui problemi di confronto delle stringhe possono essere trovate nell'articolo Nuovi consigli per l'utilizzo delle stringhe in Microsoft .NET 2.0 e anche dentro Procedure consigliate per l'uso delle stringhe in .NET Framework.


Ciascuno dei metodi menzionati (e altri) ha uno scopo particolare.La differenza fondamentale tra loro è il tipo di Enumerazione StringComparison stanno utilizzando per impostazione predefinita.Ci sono diverse opzioni:

  • Cultura attuale
  • CurrentCultureIgnoreCase
  • Cultura invariante
  • InvariantCultureIgnoreCase
  • Ordinale
  • OrdinalIgnoreCase

Ciascuno dei tipi di confronto sopra indicati si rivolge a casi d'uso diversi:

  • Ordinale
    • Identificatori interni con distinzione tra maiuscole e minuscole
    • Identificatori con distinzione tra maiuscole e minuscole in standard come XML e HTTP
    • Impostazioni relative alla sicurezza con distinzione tra maiuscole e minuscole
  • OrdinalIgnoreCase
    • Identificatori interni senza distinzione tra maiuscole e minuscole
    • Identificatori senza distinzione tra maiuscole e minuscole in standard come XML e HTTP
    • Percorsi dei file (su Microsoft Windows)
    • Chiavi/valori del registro
    • Variabili ambientali
    • Identificatori delle risorse (nomi di handle, ad esempio)
    • Impostazioni relative alla sicurezza senza distinzione tra maiuscole e minuscole
  • InvariantCulture o InvariantCultureIgnoreCase
    • Alcuni dati persistentemente rilevanti dal punto di vista linguistico
    • Visualizzazione di dati linguistici che richiedono un ordinamento fisso
  • CurrentCulture o CurrentCultureIgnoreCase
    • Dati visualizzati all'utente
    • La maggior parte degli input dell'utente

Notare che Enumerazione StringComparison così come gli sovraccarichi per i metodi di confronto delle stringhe, esistono da .NET 2.0.


Metodo String.CompareTo (String)

È infatti un'implementazione sicura di tipo Metodo IComparable.CompareTo.Interpretazione predefinita:Cultura attuale.

Utilizzo:

Il metodo CompareTo è stato progettato principalmente per l'utilizzo nelle operazioni di ordinamento o alfabetizzazione

Così

L'implementazione dell'interfaccia IComparable utilizzerà necessariamente questo metodo

Metodo String.Compare

Un membro statico di Classe di corde che ha molti sovraccarichi.Interpretazione predefinita:Cultura attuale.

Quando possibile, è necessario chiamare un sovraccarico del metodo Compare che includa un parametro StringComparison.

Metodo String.Equals

Sostituito dalla classe Object e sovraccaricato per l'indipendenza dai tipi.Interpretazione predefinita:Ordinale.Notare che:

I metodi di uguaglianza della classe String includono Uguali statici, IL operatore statico ==, e il metodo di istanza Equals.


Classe StringComparer

Esiste anche un altro modo per gestire i confronti tra stringhe, in particolare mirato all'ordinamento:

Puoi usare il Classe StringComparer per creare un confronto specifico per il tipo per ordinare gli elementi in una raccolta generica.Classi come Hashtable, Dictionary, SortedList e SortedList utilizzano la classe StringComparer per scopi di ordinamento.

Non che le prestazioni di solito siano importanti nel 99% dei casi in cui è necessario farlo, ma se dovessi farlo in un ciclo diversi milioni di volte ti consiglio vivamente di utilizzare .Equals o == perché non appena trova un carattere che non corrisponde, considera tutto falso, ma se usi CompareTo dovrà capire quale carattere è inferiore all'altro, portando a tempi di prestazione leggermente peggiori.

Se la tua app verrà eseguita in paesi diversi, ti consiglio di dare un'occhiata alle implicazioni di CultureInfo ed eventualmente utilizzare .Equals.Dato che in realtà scrivo solo app per gli Stati Uniti (e non mi interessa se non funziona correttamente da qualcuno), utilizzo sempre e semplicemente ==.

Nei moduli che hai elencato qui, non c'è molta differenza tra i due. CompareTo finisce per chiamare a CompareInfo metodo che fa un confronto utilizzando la cultura attuale; Equals è chiamato dal == operatore.

Se consideriamo i sovraccarichi, le cose cambiano. Compare E == può utilizzare solo le impostazioni cultura correnti per confrontare una stringa. Equals E String.Compare può prendere a StringComparison argomento di enumerazione che consente di specificare confronti senza distinzione di cultura o senza distinzione tra maiuscole e minuscole.Soltanto String.Compare consente di specificare a CultureInfo ed eseguire confronti utilizzando una lingua diversa da quella predefinita.

Per la sua versatilità, trovo che lo utilizzo String.Compare più di ogni altro metodo di confronto;mi permette di specificare esattamente quello che voglio.

Una GRANDE differenza da notare è che .Equals() genererà un'eccezione se la prima stringa è nulla, mentre == non lo farà.

       string s = null;
        string a = "a";
        //Throws {"Object reference not set to an instance of an object."}
        if (s.Equals(a))
            Console.WriteLine("s is equal to a");
        //no Exception
        if(s==a)
            Console.WriteLine("s is equal to a");
  • s1.Confronta con(s2): NON utilizzare se lo scopo principale è determinare se due stringhe sono equivalenti
  • s1 == s2: Non è possibile ignorare il caso
  • s1.Equals(s2, StringComparison): Genera NullReferenceException se s1 è null
  • String.Equals(s2, StringComparison): Per processo di eliminazione, questo statico il metodo è il VINCITORE (assumendo un caso d'uso tipico per determinare se due stringhe sono equivalenti)!

Usare .Equals è anche molto più semplice Leggere.

con .Equals, ottieni anche le opzioni StringComparison.molto utile per ignorare maiuscole e minuscole e altre cose.

btw, questo valuterà falso

string a = "myString";
string b = "myString";

return a==b

Poiché == confronta i valori di a e b (che sono puntatori), verrà valutato vero solo se i puntatori puntano allo stesso oggetto in memoria..Equals dereferenzia i puntatori e confronta i valori memorizzati nei puntatori.a.Equals(b) sarebbe vero qui.

e se cambi b in:

b = "MYSTRING";

allora a.Equals(b) è falso, ma

a.Equals(b, StringComparison.OrdinalIgnoreCase) 

sarebbe vero

a.CompareTo(b) chiama la funzione CompareTo della stringa che confronta i valori nei puntatori e restituisce <0 se il valore memorizzato in a è inferiore al valore memorizzato in b, restituisce 0 se a.Equals(b) è vero e >0 altrimenti.Tuttavia, questo fa distinzione tra maiuscole e minuscole, penso che ci siano forse opzioni per CompareTo per ignorare maiuscole e minuscole e simili, ma non ho tempo di guardare ora.Come altri hanno già affermato, questo verrebbe fatto per l'ordinamento.Il confronto per l'uguaglianza in questo modo comporterebbe spese generali inutili.

Sono sicuro di tralasciare alcune cose, ma penso che queste informazioni dovrebbero essere sufficienti per iniziare a sperimentare se hai bisogno di maggiori dettagli.

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