2012-03-02 17 views
17

Qual è la differenza tra == e Equals() con l'esempio? So che == viene utilizzato per confrontare dell'operatore e Equals() metodo è utilizzato per confrontare il contenuto di string.So ho provatoDifferenza tra operatore == e metodo Equals() in C#?

// first example 
string s1 = "a"; 
string s2 = "a"; 
Console.Write(a.Equals(s2)); // returns true, but if I assign "b" to s2, 
          // then result will be false 

// second example 
string s1 ="a"; 
string s2 ="a"; 
Console.Write(s1 == s2);  // returns true 

Come questo è così? Entrambi sono riferimenti a oggetti diversi. Supponiamo che consideriamo che questi sono riferimenti. Ma ho cercato di usare come questo

string s1 = new string("ab"); 
string s2 = new string("ab"); 

sto ottenendo compilazione errore di tempo che non può convertire la stringa a char

risposta

21

Ci sono diverse cose in corso. In primo luogo, in questo esempio:

string s1 = "a"; 
string s2 = "a"; 
Console.WriteLine(s1 == s2); 

Lei afferma che:

Entrambi sono differenti riferimento all'oggetto.

Questo non è vero a causa dello interno stringa.s1 e s2 sono riferimenti allo stesso oggetto. I C# specifica garantisce che - dalla sezione 2.4.4.5 della specifica C# 4:

Quando due o più stringhe letterali che sono equivalenti secondo l'operatore di uguaglianza stringa (§7.10.7) appaiono nello stesso programma, questi valori letterali stringa si riferiscono alla stessa istanza di stringa.

Quindi, in questo caso particolare, si sarebbe ancora ottenere "vero", anche se si è stampato object.ReferenceEquals(s1, s2), o se l'hai fatta usare un confronto vero identità di riferimento con ==:

object s1 = "a"; 
object s2 = "a"; 
Console.WriteLine(s1 == s2); // Still prints True due to string literal interning 

Tuttavia, anche se questi erano riferimenti a oggetti separati, == è sovraccarico per string. Il sovraccarico è una decisione in fase di compilazione - l'implementazione da utilizzare dipende dai tipi di operandi in fase di compilazione. Così, per esempio:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a == b); // Uses string's implementation, prints True 

object c = a; 
object d = b; 
Console.WriteLine(c == d); // Reference identity comparison, prints False 

Confronti che, con object.Equals(object) che è un metodo virtuale. Come accade, lo String sovraccarica questo metodo e, ma è importante che lo sostituisca. Quindi, se cambiamo il nostro codice a:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals((object) b)); 

object c = a; 
object d = b; 
Console.WriteLine(c.Equals(d)); 

... poi entrambi le chiamate di metodo nel codice compilato sarà semplicemente a object.Equals(object), ma faranno ancora sia per la stampa vera causa del polimorfismo: la realizzazione in String sarà usato.

Ecco cosa una chiamata al sovraccarico metodo sarebbe simile:

string a = new string('x', 1); 
string b = new string('x', 1); 
Console.WriteLine(a.Equals(b)); // Calls string.Equals(string) 
+0

Due domande: perché il cast di 'd' per' oggetto', dal momento che è già un oggetto? Inoltre, nella parte 'a Equals b', chiamerei sia l'override dell'oggetto, sia il sovraccarico di stringhe, quindi è più chiaro qual è la differenza. – doekman

+0

@doekman: 1) Sì, non ho bisogno del cast in quel caso. 2) Non sei sicuro di cosa intendi. –

+0

Intendo questo: vedi l'ultimo anwer. Non ho ricevuto direttamente la tua spiegazione su sovraccarico/override .... – doekman

7

Citazione dalla documentazione di Equals:

L'implementazione predefinita di Equals supporti uguaglianza di riferimento per i tipi di riferimento e uguaglianza bit per i tipi di valore. Riferimento uguaglianza significa che i riferimenti oggetto che vengono confrontati si riferiscono allo stesso oggetto . Uguaglianza per bit significa che gli oggetti confrontati hanno la stessa rappresentazione binaria.

E il == operator:

Per i tipi di valori predefiniti, l'operatore di uguaglianza (==) restituisce vero se i valori dei suoi operandi sono uguali, false altrimenti. Per i tipi di riferimento diversi dalla stringa, == restituisce true se i suoi due operandi si riferiscono a lo stesso oggetto. Per il tipo di stringa, == confronta i valori delle stringhe .

Ora torna alla tua domanda: perché s1 == s2 restituisce vero? Le stringhe sono bestie speciali in .NET. Rappresentano tipi di riferimento immutabili. Sono internati in .NET. Ciò significa che se si hanno 2 costanti di stringa con lo stesso valore, si riferiscono alla stessa istanza dell'oggetto in fase di esecuzione.

Citazione dal documentation:

Il Common Language Runtime conserva stoccaggio stringa mantenendo un tavolo , denominata pool interno, che contiene un solo riferimento alle ogni stringa letterale unica dichiarata o creata a livello di codice in il tuo programma Di conseguenza, un'istanza di una stringa letterale con un valore particolare esiste solo una volta nel sistema.

+0

Non è * esclusivamente * a causa dell'internamento. Interning è il motivo per cui funzionerebbe anche se fossero dichiarati di tipo 'oggetto'. Ma anche i riferimenti a oggetti stringa distinti con lo stesso contenuto funzionerebbero fino a quando i tipi di tempo di compilazione coinvolti sono entrambi stringa, a causa dell'overloading dell'operatore. La documentazione che hai citato è fuorviante in quanto suggerisce che ci sia un trattamento speciale * solo per le stringhe * - non c'è, è solo che la stringa è * un * tipo di riferimento che sovraccarica l'operatore ==. –

+1

Si noti inoltre che l'interning è un dettaglio della lingua -.NET fornisce i meccanismi, ma sarebbe del tutto possibile avere un linguaggio Dumb # che era lo stesso di C# in ogni modo, eccetto che senza costante internamento di stringhe. –

2

Stai pensando sembrano Java-esque. In Java, l'operatore == non può essere personalizzato, quindi per i tipi di riferimento significa sempre uguaglianza di riferimento, mentre significa uguaglianza di valore per i tipi primitivi. D'altra parte, Equals serve per controllare l'uguaglianza dei valori nei tipi di riferimento.

Le cose sono diverse in C#, però. Sia Equals e == possono avere implementazioni personalizzate. La differenza è che Equals è un metodo virtuale (di istanza), mentre operator== è un metodo statico. A parte questo, possono comportarsi esattamente allo stesso modo.

Per impostazione predefinita, sia Equals sia == controllano l'uguaglianza di riferimento per i tipi di riferimento e l'uguaglianza di valore per i tipi di valore. Tuttavia, per string, entrambi sono personalizzati per controllare l'uguaglianza dei valori.

Problemi correlati