c#: ReferenceEquals, Equals, Operatore ==

  • Il metodo ReferenceEquals verifica le uguaglianze per riferimento
  • Il metodo Equals verifica le uguaglianze per valore
  • l’operatore “==” a volte per riferimento e a volte per valore.

Ecco qualche esempio:

Se dichiariamo a e b in questo modo:

System.Object a = new System.Object();
System.Object b = a;

a e b sono riferimento allo stesso oggetto. Per avere la prova sul campo basta eseguire questo codice:

class Program
{
   static void Main(string[] args)
   {
      ObjectClass o1 = new ObjectClass();
      ObjectClass o2 = o1;
 
      o1.Value = 3;
      Console.WriteLine("o1: {0}", o1.Value);
      Console.WriteLine("o2: {0}", o2.Value);
      o2.Value = 5;
      Console.WriteLine("o1: {0}", o1.Value);
      Console.WriteLine("o2: {0}", o2.Value);</code>
 
      Console.WriteLine("ReferenceEquals: {0}", System.Object.ReferenceEquals(o1, o2));
   }
 
   class ObjectClass
   {
      private int value;</code>
 
      public int Value
      {
         get { return this.value; }
         set { this.value = value; }
      }
   }
}

Il risultato è:

o1: 3
o2: 3
o1: 5
o2: 5
ReferenceEquals: True
Equals: True
==: True

quindi modificare uno dei due oggetti significa modificare anche l’altro. Il metodo System.Object.ReferenceEquals verifica appunto l’uguaglianza per riferimento di due oggetti.

Se invece li dichiariamo così:

ObjectClass o1 = new ObjectClass();
ObjectClass o2 = new ObjectClass();

o1.Value = 3;
o2.Value = 3;
Console.WriteLine("ReferenceEquals: {0}", System.Object.ReferenceEquals(o1, o2));
Console.WriteLine("Equals: {0}", System.Object.Equals(o1, o2));
Console.WriteLine("==: {0}", o1 == o2);

il risultato è:

ReferenceEquals: False
Equals: False
==: False

  • ReferenceEquals è False perche o1 e o2 sono due oggetti separati, che nulla hanno in comune se non il valore uguale.
  • Equals è False perchè sto confrontando due oggetti che ho creato io, e in cui non ho specificato nessun ovverride per il metodo Equals.
  • == è false perchè in questo caso si comporta come ReferenceEquals

Un esempio interessante è questo, sulle stringhe:

String s1 = "pippo";
String s2 = "pippo";

Console.WriteLine("Risultato ReferenceEquals: {0}", System.Object.ReferenceEquals(s1, s2));
Console.WriteLine("Risultato Equals: {0}", System.Object.Equals(s1, s2));
Console.WriteLine("Risultato ==: {0}", s1 == s2);

il risultato è:

Risultato ReferenceEquals: True
Risultato Equals: True
Risultato ==: True

  • ReferenceEquals restituisce True perche s1 e s2 sono riferimento allo stesso oggetto. Così funziona c# quando si dichiarano più stringhe con lo stesso valore.
  • Equals resituisce True perchè sto confrontando un’oggetto con se stesso
  • == restituisce True perchè in questo caso si comporta come Equals

Invece:

String s1 = "pippo";
String s2 = String.Copy(s1);

Console.WriteLine("Risultato ReferenceEquals: {0}", System.Object.ReferenceEquals(s1, s2));
Console.WriteLine("Risultato Equals: {0}", System.Object.Equals(s1, s2));
Console.WriteLine("Risultato ==: {0}", s1 == s2);

(il metodo String.Copy crea una nuova istanza con valore uguale a quella in input)

genera questo risultato:

Risultato ReferenceEquals: False
Risultato Equals: True
Risultato ==: True

  • ReferenceEquals restituisce false, perchè s1 e s2 non puntano allo stesso oggetto
  • Equals restituisce True, perchè s1 e s2 hanno lo stesso valore
  • == restituisce True perchè in questo caso si comporta come Equals

L’operatore ==, al contrario del Java, può essere usato per il confronto fra stringhe. Ma vediamo cosa succede se facciamo un downgrade di String a Object:

String s1 = "pippo";
String s2 = String.Copy(s1);

Console.WriteLine("Risultato ReferenceEquals: {0}", System.Object.ReferenceEquals(s1, s2));
Console.WriteLine("Risultato ReferenceEquals: {0}", System.Object.ReferenceEquals((Object)s1, (Object)s2));

Console.WriteLine("Risultato Equals: {0}", System.Object.Equals(s1, s2));
Console.WriteLine("Risultato Equals: {0}", System.Object.Equals((Object)s1, (Object)s2));

Console.WriteLine("Risultato ==: {0}", s1 == s2);
Console.WriteLine("Risultato ==: {0}", (Object)s1 == (Object)s2);

Il risultato è:

Risultato ReferenceEquals: False
Risultato ReferenceEquals: False
Risultato Equals: True
Risultato Equals: True
Risultato ==: True
Risultato ==: False

Il suo comportamento è definito dall’msdn di mamma Microsoft:

For predefined value types, the equality operator (==) returns true if the values of its operands are equal, false otherwise. For reference types other than string, == returns true if its two operands refer to the same object. For the string type, == compares the values of the strings.

Ovvero: l’uguaglianza è verificata per valore se è verificata fra tipi predefiniti e stringhe, in tutti gli altri casi è per riferimento.

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>