Differenza tra == e Equals

Scritto da  Roberto Albano il lunedì 11 aprile 2011  •  Linguaggio: C#   • Livello: 100


Molti pensano che nella comparazione tra due oggetti si possa utilizzare in maniera indifferente sia l'operatore di uguaglianza '==' sia il metodo Equals (presente già dalla classe object).

Questo in realtà non è vero dato che, in base al tipo di comparazione, si possono ottenere risultati diversi.

Partiamo subito con un esempio:

int i1 = 100;
int i2 = 100;
bool b1 = ( i1 == i2 );       // true
bool b2 = ( i1.Equals(i2) );  // true
 
StringBuilder sb1 = new StringBuilder("prova");
StringBuilder sb2 = new StringBuilder("prova");
bool b3 = ( sb1 == sb2 );       // false
bool b4 = ( sb1.Equals(sb2) );  // true

 

Questo succede perché la comparazione tra value types (come nel caso degli int) avviene sempre a livello di valore, quindi '==' ed Equals si comportano allo stesso modo, mentre nella comparazione tra reference types (come nel caso della classe StringBuilder) questo avviene a livello di puntamento per '==' e a livello di valore per Equals.

Di fatto Equals è un metodo della classe object, che può essere sottoposto ad "override" (cioè a ridefinizione) nelle classi in cui si abbia la necessità di definire l'uguaglianza in maniera diversa. 

public override bool Equals(object obj)
{
    // ...
}

 

Quindi nella classe StringBuilder il metodo Equals verifica il valore (in questo caso della stringa) presente nell'istanza mentre l'operatore '==' verifica se fisicamente gli oggetti della comparazione rappresentino effettivamente lo stesso oggetto (ovvero se puntano di fatto allo stesso spazio di memoria).

Qualcuno noterà subito che se eseguiamo un codice del genere: 

string s1 = "prova";
string s2 = "prova";
bool b5 = ( s1 == s2 );       // true
bool b6 = ( s1.Equals(s2) );  // true

 

otterremo sempre un'uguaglianza, anche se la classe string è, di fatto, un reference type.
In questo caso nella classe string è stato fatto un "override" dell'operatore '==':

public static bool operator == (object obj1, object obj2)
{
    // ...
}

 

(per completezza diciamo che nella classe string è stato ridefinito in maniera analoga anche l'operatore '!=')

Teniamo sempre bene a mente la possibilità di dover eseguire questi "override" quando sviluppiamo le nostre classi. 


Tags: C#,CLR

 
x