2009-05-13 12 views
17

Esistono diversi modi per confrontare le stringhe. Ci sono guadagni in termini di prestazioni facendo un modo piuttosto che un altro?Performance comparativa delle stringhe in C#

ho sempre optato per confrontare le stringhe in questo modo:

string name = "Bob Wazowski"; 
if (name.CompareTo("Jill Yearsley") == 0) { 
    // whatever... 
} 

Ma trovo poche persone che fanno questo, e se qualcosa, vedo sempre più persone solo facendo un confronto == dritta, che a mia conoscenza è il peggior modo di confrontare le stringhe. Ho sbagliato?

Inoltre, fa una differenza nel modo in cui si confrontano le stringhe nelle query LINQ? Per esempio, mi piace fare le seguenti operazioni:

var results = from names in ctx.Names 
       where names.FirstName.CompareTo("Bob Wazowski") == 0 
       select names; 

Ma ancora una volta, vedo poche persone che fanno confronti tra stringhe in questo modo nelle loro query LINQ.

+0

possibile duplicato del [Differenze nella stringa di confrontare metodi in C#] (http://stackoverflow.com/questions/44288/differences-in-string-compare-methods-in-c-sharp) – crowder

+0

si potrebbe desiderare per vedere http://rhale78.wordpress.com/2011/05/16/string-equality-and-performance-in-c/ – nawfal

risposta

22

Secondo riflettore

"Hello" == "World" 

è uguale

String.Equals("Hello", "World"); 

che determina sostanzialmente se sono lo stesso oggetto di riferimento, se uno dei due è nullo, che sarebbe un falso automatica se uno era nullo e l'altro no, quindi confronta ciascun carattere in un ciclo non sicuro. Quindi non si preoccupa affatto delle regole culturali, che di solito non sono un grosso problema.

e

"Hello".CompareTo("World") == 0 

è uguale

CultureInfo.CurrentCulture.CompareInfo.Compare("Hello", "World", CompareOptions.None); 

Questo è fondamentalmente l'opposto quanto riguarda la funzionalità. Prende in considerazione la cultura, la codifica e tutto il resto con la stringa nel contesto.

quindi immagino che String.CompareTo è un paio di ordini di grandezza più lento rispetto l'operatore di uguaglianza.

come per il vostro LINQ non importa se si sta utilizzando LINQ to SQL, perché entrambi saranno generare lo stesso SQL

var results = from names in ctx.Names 
      where names.FirstName.CompareTo("Bob Wazowski") == 0 
      select names; 

di

SELECT [name fields] 
FROM [Names] AS [t0] 
WHERE [t0].FirstName = @p0 

in modo che davvero non sono guadagnando qualcosa per LINQ-to-SQL tranne che per leggere codice più difficile e probabilmente più parsing delle espressioni. Se si utilizza LINQ solo per gli array standard, si applicano le regole di cui sopra.

+2

string.Equals non esegue un controllo di uguaglianza di riferimento in .NET 4.0, è sovraccarico in stringa per confrontare le stringhe effettive. (Non sarei sorpreso se questo fosse sempre vero però. – Massif

+0

AFAIK, string.Equals considera anche la cultura. –

+1

@ La risposta di Massif è corretta. String.Equals() e == non confrontano i riferimenti agli oggetti. Per dimostrarlo a te stesso, chiama Object.ReferenceEquals (x, y), dove x è una stringa hardcoded e y è dato sulla riga di comando. – GreenRibbon

2

C'è stata una domanda abbastanza simile recentemente riguardo al modo più veloce per tagliare una stringa, ma fondamentalmente era il benchmarking dei diversi modi di confrontarli.

È possibile verificare i parametri on this post.

+0

ho controllato il post. Grazie, è stato utile. Ha appena riaffermato che string.length è il modo più veloce per verificare se una stringa è vuota, a meno che non abbia frainteso i risultati del benchmark. – Jagd

15

A mio parere, è necessario utilizzare sempre il modo più chiaro, che utilizza ==!

Questo può essere compreso direttamente: quando "Ciao" è uguale a "Mondo", quindi fare qualcosa.

if ("Hello" == "World") 
    // ... 

Internamente, String::Equals viene invocato esplicitamente che esiste a questo scopo - Confronto tra due stringhe per uguaglianza. (Questo non ha nulla a che fare con puntatori e riferimenti, ecc.)

Questo non è immediatamente chiaro - Perché confrontare a zero?

if ("Hello".CompareTo("World") == 0) 

.CompareTo non è progettato solo per il controllo di uguaglianza (== avete per questo) - Esso mette a confronto due stringhe. Si utilizza .CompareTo per determinare se una stringa è "maggiore" di un'altra. È possibile verificare l'uguaglianza perché produce zero per stringhe uguali, ma non è quello per cui è concepito.

Quindi ci sono diversi metodi e interfacce per il controllo di uguaglianza (IEquatable, operatore ==) e confrontando (IComparable)

Linq non si comporta diverso rispetto alla normale C# qui.

+2

L'OP non chiedeva quale sia il modo più chiaro per scrivere un confronto tra stringhe. Ciò che è chiaro a uno potrebbe non essere chiaro a un altro. –

8

Leggi Jeff's The Best Code is No Code at All. foo.CompareTo(bar) == 0: disordine visivo orribile. Occupa molto spazio e non trasmette alcun significato interessante. In effetti, enfatizza molte cose irrilevanti che allontanano l'attenzione dal vero problema.

Se c'è ragione non ben definito per l'utilizzo di questa variante più a lungo, non lo fanno.

Per quanto riguarda le prestazioni: semplicemente non importa per questo semplice caso. Se l'operatore di uguaglianza == dovesse davvero andare peggio di CompareTo, non esitare a presentare una segnalazione di bug con Microsoft. Questo non deve accadere.

1

Se l'operatore di uguaglianza effettivamente ha funzionato peggio di CompareTo - Microsoft non renderebbe l'implementazione della chiamata dell'operatore di uguaglianza CompareTo?

Basta usare l'operatore di uguaglianza per verificare l'uguaglianza.

0

Generalmente uso String.Compare con il sovraccarico che richiede un parametro StringComparison, perché in questo caso posso essere assolutamente esplicito sull'opportunità o meno del confronto tra maiuscole e minuscole. Questo richiede .NET 2.0 o versioni successive.

Il più veloce è StringComparison.Ordinal (o StringComparison.OrdinalIgnoreCase se case-non sensibile) per confronti che non sono sensibili alla cultura.

Il problema con l'utilizzo di == è che non è chiaro se l'autore abbia preso in considerazione la sensibilità al caso e alla cultura.

C'è un buon articolo MSDN sull'oggetto here.

+0

== è uguale a() e Equals() rende CaseSens. & CultureInsens. ricerca (la più veloce, facile da ricordare). Calling Equals (var, StringComparison.OrdinalCaseInsensetive) è più lento della chiamata a Equals(), quindi nel caso in cui stai confrontando milioni di stringhe è meglio usare Equals() anziché la versione == e 2arg. – Grigory

0

Per migliore modo per confrontare string 's in C# è quello di utilizzare i a.Equals(b) dove un e b sono stringhe.Questo è il modo migliore per confrontare la stringa perché confronta i valori degli oggetti a e b e non dipende dal riferimento degli oggetti.

Se avete intenzione di utilizzare simbolo "==", il risultato sarà uguale se entrambi gli oggetti hanno lo stesso riferimento, ma si avrà un problema quando hanno riferimenti diversi e hanno lo stesso valore.

Procedimento compareTo è il modo migliore per utilizzare se il test se l'altra stringa viene precede, segue o apparire nella stessa posizione dell'altro stringa in cui si tornerà rispettivamente valore negativo, valore positivo o zero. Si tornerà valore positivo anche se il parametro è null

+0

È già chiaro dalle altre risposte, ma solo per essere sicuro: questo è sbagliato. la stringa sovraccarica l'operatore '==' –

4

Beh MSDN afferma si shoul utilizzare la funzione di confronto a seconda del compito è necessario eseguire:

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

Quindi, se la sua non sull'ordinamento e il valore retrun non è importante, direi che si dovrebbe usare il:

first.Equals(second) o se il confronto è cultura specifica, ad esempio in lingue come in tedesco:

String.Equals(first, second, StringComparison.CurrentCulture)

Date un'occhiata a questi link:

How to: Compare Strings (C# Programming Guide)

String.CompareTo Method (Object)

0

Here è la guida più completa MSDN e disponibile per il confronto di stringhe che ho trovato.

Utilizzare i confronti con StringComparison.Ordinal o StringComparison.OrdinalIgnoreCase per migliorare le prestazioni.