Il presente articolo è stato tradotto manualmente. Passare il puntatore sulle frasi nell'articolo per visualizzare il testo originale.
Traduzione
Originale
Questo argomento non è stato ancora valutato - Valuta questo argomento

Metodo Object.Equals (Object)

Determina se l'oggetto Object specificato è uguale all'oggetto Object corrente.

Spazio dei nomi:  System
Assembly:  mscorlib (in mscorlib.dll)
public virtual bool Equals(
	Object obj
)

Parametri

obj
Tipo: System.Object
Oggetto da confrontare con l'oggetto corrente.

Valore restituito

Tipo: System.Boolean
true se l'oggetto Object specificato è uguale all'oggetto Object corrente; in caso contrario, false.

L'implementazione predefinita del metodo Equals supporta l'uguaglianza dei riferimenti per i tipi di riferimento e l'uguaglianza bit per bit per i tipi di valore. Per uguaglianza dei riferimenti si intende che i riferimenti all'oggetto confrontati fanno riferimento allo stesso oggetto. Per uguaglianza bit per bit si intende invece che gli oggetti confrontati presentano la stessa rappresentazione binaria.

Si noti che un tipo derivato può eseguire l'override del metodo Equals per implementare l'uguaglianza di valori. Per uguaglianza di valori si intende che gli oggetti confrontati hanno lo stesso valore anche se presentano rappresentazioni binarie diverse. Ad esempio, si considerino due oggetti Decimal che rappresentano i numeri 1,10 e 1,1000. Gli oggetti Decimal non presentano uguaglianza bit per bit perché sono caratterizzati da rappresentazioni binarie diverse per tenere in considerazione il diverso numero diverso di zero finali. Tuttavia, gli oggetti presentano uguaglianza di valori perché i numeri 1,10 e 1,1000 sono considerati uguali ai fini del confronto poiché gli zero finali non sono significativi.

Note per gli implementatori

Il metodo può essere sottoposto a override da una classe derivata. Molti tipi di dati di base restituiscono, ad esempio, true se entrambi gli oggetti rappresentano lo stesso valore; in caso contrario, false.

Il metodo confronta soltanto tipi primitivi e oggetti. Per confrontare strutture più complesse, come ad esempio le matrici di oggetti, deve essere sottoposto a override.

Le seguenti istruzioni devono essere true per tutte le implementazioni del metodo Equals. Nell'elenco, x, y e z rappresentano riferimenti a oggetti che non sono null.

  • x.Equals(x) restituisce true, eccetto nei casi in cui sono compresi tipi a virgola mobile. Vedere IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems.

  • x.Equals(y) restituisce lo stesso valore di y.Equals(x).

  • x.Equals(y) restituisce true se x e y sono NaN.

  • Se (x.Equals(y) && y.Equals(z)) restituisce true, x.Equals(z) restituisce true.

  • Le chiamate successive a x.Equals(y) restituiscono lo stesso valore finché non vengono modificati gli oggetti a cui fanno riferimento x e y.

  • x.Equals( null ) restituisce false.

Vedere GetHashCode per le ulteriori funzionalità richieste che riguardano il metodo Equals.

Le implementazioni di Equals non devono generare eccezioni.

È possibile confrontare l'oggetto corrente con un altro oggetto per l'uguaglianza dei riferimenti chiamando il metodo ReferenceEquals. In Visual Basic è possibile utilizzare anche la parola chiave is (ad esempio If Me Is otherObject Then …).

Per alcuni tipi di oggetti è preferibile che il metodo Equals esegua il test di uguaglianza dei valori anziché dei riferimenti. Tali implementazioni di Equals restituiscono true se i due oggetti hanno lo stesso "valore", anche se non sono della stessa istanza. L'implementatore del tipo stabilisce ciò che costituirà il "valore" di un oggetto, ma in genere si tratta di parte o di tutti i dati memorizzati nelle variabili di istanza dell'oggetto. Il valore, ad esempio, di un oggetto String si basa sui caratteri della stringa; il metodo Equals della classe String restituisce true ogni due istanze di stringa contenenti esattamente gli stessi caratteri nello stesso ordine.

I tipi che implementano l'interfaccia IComparable devono eseguire l'ovveride del metodo Equals.

I tipi che eseguono l'override del metodo Equals devono eseguire anche l'override del metodo GetHashCode. In caso contrario, Hashtable potrebbe non funzionare correttamente.

Se il linguaggio di programmazione utilizzato supporta l'overload dell'operatore e si sceglie di eseguire l'overload dell'operatore di uguaglianza per un determinato tipo, questo tipo deve eseguire l'override del metodo Equals. Tali implementazioni del metodo Equals devono restituire lo stesso risultato dell'operatore di uguaglianza. L'applicazione di queste indicazioni garantisce che il codice della libreria di classi che utilizza il metodo Equals, ad esempio ArrayList e Hashtable, agisca conformemente al modo in cui il codice dell'applicazione utilizza l'operatore di uguaglianza.

Le seguenti indicazioni sono applicabili all'implementazione di un tipo di valore:

  • Considerare l'override del metodo Equals per ottenere prestazioni superiori rispetto a quelle offerte dall'implementazione predefinita di Equals su ValueType.

  • Se si esegue l'override di Equals e il linguaggio supporta l'overload dell'operatore, eseguire l'overload dell'operatore di uguaglianza del tipo di valore utilizzato.

Le seguenti indicazioni sono applicabili per l'implementazione di un tipo di riferimento:

  • Considerare l'override del metodo Equals su un tipo di riferimento se la semantica del tipo si basa sul fatto che il tipo rappresenta dei valori.

  • La maggior parte dei tipi di riferimento non deve eseguire l'overload dell'operatore di uguaglianza, anche se esegue l'override di Equals. Se tuttavia si implementa un tipo di riferimento che presumibilmente dispone di una semantica di valori, come ad esempio un tipo di numero complesso, è necessario eseguire l'override dell'operatore di uguaglianza.

Nell'esempio di codice che segue viene confrontata l'istanza corrente con un altro oggetto.


using System;
class Program
{
    static void Main(string[] args)
    {
        Object Obj1 = new Object();
        Object Obj2 = new Object();
        Console.WriteLine(Obj1.Equals(Obj2));
        Obj2 = Obj1;
        Console.WriteLine(Obj1.Equals(Obj2)); 
    }
}

/* This example produces the following output:
False
True
 */


Nell'esempio che segue viene descritta una classe Point che esegue l'override del metodo Equals per fornire l'uguaglianza di valori e una classe Point3D, derivata da Point. Poiché l'override di Point eseguito dal metodo Equals è il primo elemento nella catena di eredità a introdurre l'uguaglianza di valori, non viene richiamato il metodo Equals della classe base, che è ereditata dall'oggetto Object e utilizzata per ricercare l'uguaglianza referenziale. Ciononostante, Point3D.Equals chiama il metodo Point.Equals perché Point implementa Equals in un modo che consente l'uguaglianza di valori.


using System;

class Point: Object {
   protected int x, y;

   public Point() {
     this.x = 0;
     this.y = 0;
   }

   public Point(int X, int Y) {
      this.x = X;
      this.y = Y;
   }

   public override bool Equals(Object obj) {
      //Check for null and compare run-time types.
      if (obj == null || GetType() != obj.GetType()) return false;
      Point p = (Point)obj;
      return (x == p.x) && (y == p.y);
   }

   public override int GetHashCode() {
      return x ^ y;
   }
}


class Point3D: Point {
   int z;

   public Point3D(int X, int Y, int Z) {
      this.x = X;
      this.y = Y;
      this.z = Z; 
   }

   public override bool Equals(Object obj) {
      return base.Equals(obj) && z == ((Point3D)obj).z;
   }

   public override int GetHashCode() {
      return base.GetHashCode() ^ z;
   }
}

class MyClass {

  public static void Main() {
     Point point2D = new Point(5, 5);
     Point3D point3Da = new Point3D(5, 5, 2);
     Point3D point3Db = new Point3D(5, 5, 2);

     if (!point2D.Equals(point3Da)) {
        Console.WriteLine("point2D does not equal point3Da.");
     }
     if (!point3Db.Equals(point2D)) {
        Console.WriteLine("Likewise, point3Db does not equal point2D.");
     }
     if (point3Da.Equals(point3Db)) {
        Console.WriteLine("However, point3Da equals point3Db.");
     }

  } 
}
// ----------------------------------
// Output should be:
// 
// point2D does not equal point3Da.
// Likewise, point3Db does not equal point2D.
// However, point3Da equals point3Db.


Il metodo Point.Equals verifica che l'argomento obj non sia null e che faccia riferimento a un'istanza dello stesso tipo dell'oggetto. Se una di queste verifiche ha esito negativo, il metodo restituisce false.

Il metodo Equals si avvale di GetType per determinare se i tipi in fase di esecuzione dei due oggetti sono identici. In questo caso non viene utilizzato typeof, perché restituisce il tipo statico. Se il metodo ha utilizzato un controllo del formato obj is Point, il controllo restituirà true nei casi in cui obj è un'istanza di una classe derivata di Point, anche se obj e l'istanza corrente non sono dello stesso tipo di runtime. Una volta verificato che entrambi gli oggetti sono dello stesso tipo, il metodo esegue il cast di obj al tipo Point e restituisce il risultato del confronto tra variabili di istanza dei due oggetti.

In Point3D.Equals il metodo ereditato Equals viene chiamato prima dell'esecuzione di qualsiasi operazione; il metodo ereditato Equals verifica che obj non sia null, che obj sia un'istanza della stessa classe di questo oggetto e che le variabili di istanza ereditate corrispondano. Soltanto quando il metodo ereditato Equals restituisce true, vengono confrontate le variabili di istanza introdotte nella classe derivata. In particolare, il cast a Point3D non viene eseguito se non si è stabilito che obj è di tipo Point3D o una classe derivata di Point3D.

Nell'esempio precedente viene utilizzato operator ==, ossia l'operatore di uguaglianza, per confrontare le singole variabili di istanza. In alcuni casi è opportuno utilizzare il metodo Equals per confrontare le variabili di istanza in una implementazione di Equals, come descritto nell'esempio di codice che segue.


using System;

class Rectangle {
   Point a, b;

   public Rectangle(int upLeftX, int upLeftY, int downRightX, int downRightY) {
      this.a = new Point(upLeftX, upLeftY);
      this.b = new Point(downRightX, downRightY);
   }

   public override bool Equals(Object obj) {
     // Performs an equality check on two rectangles (Point object pairs).
      if (obj == null || GetType() != obj.GetType()) return false;
      Rectangle r = (Rectangle)obj;
      //Uses Equals to compare variables.
      return a.Equals(r.a) && b.Equals(r.b);
   }

   public override int GetHashCode() {
      return a.GetHashCode() ^ b.GetHashCode();
   }
}

// Class Point added for clean compile
class Point {
  private int x;
  private int y;

  public Point(int X, int Y) {
     this.x = X;
     this.y = Y;
  }

  public override bool Equals (Object obj) {
     // Performs an equality check on two points (integer pairs).
     if (obj == null || GetType() != obj.GetType()) return false;
     Point p = (Point)obj;
     return (x == p.x) && (y == p.y);
  }

  public override int GetHashCode() {
     return x.GetHashCode() ^ y.GetHashCode();
  }

}

class MyClass {
   public static void Main() {

      Rectangle r1 = new Rectangle(0, 0, 100, 200);
      Rectangle r2 = new Rectangle(0, 0, 100, 200);
      Rectangle r3 = new Rectangle(0, 0, 150, 200);

      if (r1.Equals(r2)) {
         Console.WriteLine("Rectangle r1 equals rectangle r2!");
      }
      if (!r2.Equals(r3)) {
         Console.WriteLine("But rectangle r2 does not equal rectangle r3.");
      }
   }
}
// ------------------------------
// Output should be:
// Rectangle r1 equals rectangle r2!
// But rectangle r2 does not equal rectangle r3.


In alcuni linguaggi, C# e Visual Basic, l'overload degli operatori è supportato. Quando un tipo esegue l'overload dell'operatore di uguaglianza, deve inoltre eseguire l'override del metodo Equals per fornire la stessa funzionalità. Questo risultato in genere si ottiene scrivendo il metodo Equals nei termini dell'operatore di uguaglianza sottoposto a overload, come nell'esempio riportato di seguito.


using System;

public struct Complex {
   public double re, im;

   public override bool Equals(Object obj) {
      return obj is Complex && this == (Complex)obj;
   }

   public override int GetHashCode() {
      return re.GetHashCode() ^ im.GetHashCode();
   }

   public static bool operator ==(Complex x, Complex y) {
      return x.re == y.re && x.im == y.im;
   }

   public static bool operator !=(Complex x, Complex y) {
      return !(x == y);
   }
}

class MyClass {

  public static void Main() {
    Complex cmplx1, cmplx2;

    cmplx1.re = 4.0;
    cmplx1.im = 1.0;

    cmplx2.re = 2.0;
    cmplx2.im = 1.0;

    if (cmplx1 != cmplx2)
      Console.WriteLine("The two objects are not equal.");
    if (! cmplx1.Equals(cmplx2))
      Console.WriteLine("The two objects are not equal.");

    cmplx2.re = 4.0;

    if (cmplx1 == cmplx2) 
      Console.WriteLine("The two objects are now equal!");
    if (cmplx1.Equals(cmplx2)) 
      Console.WriteLine("The two objects are now equal!");
  }
}
// The example displays the following output:
//       The two objects are not equal.
//       The two objects are not equal.
//       The two objects are now equal!
//       The two objects are now equal!


Poiché Complex è una struttura C#, ossia un tipo di valore, non è possibile ottenere derivazioni; di conseguenza, è necessario che il metodo Equals non confronti i risultati di GetType per ciascun oggetto, ma che possa invece utilizzare l'operatore is per verificare il tipo del parametro obj.

.NET Framework

Supportato in: 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Supportato in: 4, 3.5 SP1

Supportato in:

Windows 7, Windows Vista SP1 o versione successiva, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (componenti di base del server non supportati), Windows Server 2008 R2 (componenti di base del server supportati con SP1 o versione successiva), Windows Server 2003 SP2

.NET Framework non supporta tutte le versioni di ciascuna piattaforma. Per un elenco delle versioni supportate, vedere Requisiti di sistema di .NET Framework.

Data

Cronologia

Motivo

Ottobre 2010

Revisione dell'ultimo esempio.

Commenti e suggerimenti dei clienti.

Il documento è risultato utile?
(1500 caratteri rimanenti)
Contenuto della community Aggiungi
Microsoft sta conducendo un sondaggio in linea per comprendere l'opinione degli utenti in merito al sito Web di MSDN. Se si sceglie di partecipare, quando si lascia il sito Web di MSDN verrà visualizzato il sondaggio in linea.

Si desidera partecipare?