Object.Equals (Método) (Object) (System)

Cambiar vista:
Sin script
Biblioteca de clases de .NET Framework
Object.Equals (Método) (Object)
Este artículo se tradujo de forma manual. Para mostrar esta página y el contenido original en inglés al mismo tiempo, cambie a Lightweight según sus preferencias de visualización.

Determina si el objeto Object especificado es igual al objeto Object actual.

Espacio de nombres:  System
Ensamblado:  mscorlib (en mscorlib.dll)
Sintaxis

Visual Basic
Public Overridable Function Equals ( _
	obj As Object _
) As Boolean
C#
public virtual bool Equals(
	Object obj
)
Visual C++
public:
virtual bool Equals(
	Object^ obj
)
F#
abstract Equals : 
        obj:Object -> bool 
override Equals : 
        obj:Object -> bool 

Parámetros

obj
Tipo: System.Object
Objeto que se va a comparar con el objeto actual.

Valor devuelto

Tipo: System.Boolean
Es true si el objeto Object especificado es igual al objeto Object actual; en caso contrario, es false.
Comentarios

La implementación predeterminada de Equals admite la igualdad de referencias para los tipos de referencia, y la igualdad bit a bit para los tipos de valor. La igualdad de referencias significa que las referencias de objeto que se comparan hacen referencia al mismo objeto. La igualdad bit a bit significa los objetos que se comparan tienen la misma representación binaria.

Observe que un tipo derivado podría reemplazar el método Equals para implementar la igualdad de valores. La igualdad de valores significa que los objetos comparados tienen el mismo valor aunque tengan representaciones binarias diferentes. Por ejemplo, considere dos objetos Decimal que representan los números 1,10 y 1,1000. Los objetos Decimal no tienen igualdad bit a bit porque tienen representaciones binarias diferentes para tener en cuenta el diferente número de ceros finales. Sin embargo, los objetos tienen igualdad de valores porque los números 1,10 y 1,1000 se consideran iguales a efectos de comparación, ya que los ceros finales no son significativos.

Notas para los implementadores

Este método puede ser reemplazado por una clase derivada. Por ejemplo, muchos de los tipos de datos base devuelven true si ambos objetos representan el mismo valor; en caso contrario, devuelven false.

Este método sólo compara tipos primitivos y objetos. Se debe reemplazar para comparar estructuras más complejas, como matrices de objetos.

Las instrucciones siguientes deben ser true para todas las implementaciones del método Equals. En la lista, x, y, y z representan referencias a objetos que no son null.

  • x.Equals(x) devuelve true, salvo en los casos en que hay tipos de punto flotante. Consulte la norma IEC 60559:1989, Binary Floating-point Arithmetic for Microprocessor Systems (aritmética de punto flotante de tipo binario para sistemas de microprocesadores).

  • x.Equals(y) devuelve el mismo valor que y.Equals(x).

  • x.Equals(y) devuelve true si tanto x como y son NaN.

  • Si (x.Equals(y) && y.Equals(z)) devuelve true, entonces x.Equals(z) devuelve true.

  • Las llamadas sucesivas a x.Equals(y) devuelven el mismo valor siempre y cuando no se modifiquen los objetos a los que hacen referencia x e y.

  • x.Equals(null) devuelve false.

Vea GetHashCode para obtener información sobre otros comportamientos requeridos pertenecientes al método Equals.

Las implementaciones de Equals no deben producir excepciones.

Puede comparar el objeto actual con otro objeto para la igualdad de la referencia llamando al método ReferenceEquals. En Visual Basic, puede utilizar la palabra clave (por ejemplo, If Me Is otherObject Then …) is también.

En el caso de algunos tipos de objetos, es conveniente realizar una comprobación de Equals para comprobar así la igualdad de valores en lugar de la igualdad referencial. Este tipo de implementaciones de Equals devuelve true si los dos objetos tienen el mismo "valor", aunque no sean la misma instancia. El implementador de tipos decide qué es lo que constituye el "valor" de un objeto, pero suele ser una parte o la totalidad de los datos almacenados en las variables de instancia del objeto. Por ejemplo, el valor de String se basa en los caracteres de la cadena; el método Equals de la clase String devuelve true en el caso de que dos instancias de cadena contengan exactamente los mismos caracteres y en el mismo orden.

Los tipos que implementan IComparable deben reemplazar el método Equals.

Los tipos que reemplazan Equals también deben reemplazar GetHashCode; de lo contrario, puede que Hashtable no funcione correctamente.

Si el lenguaje de programación admite la sobrecarga de operadores y si se decide sobrecargar el operador de igualdad correspondiente a un tipo determinado, dicho tipo debe reemplazar el método Equals. Estas implementaciones del método Equals deben devolver los mismos resultados que el operador de igualdad. El cumplimiento de esta instrucción garantiza que el código de la biblioteca de clases que utiliza Equals (como ArrayList y Hashtable) se comporte de manera coherente con respecto a la forma en que el código de la aplicación utiliza el operador de igualdad.

Las instrucciones siguientes sirven para implementar un tipo de valor:

  • Considere la posibilidad de reemplazar Equals para obtener un rendimiento mayor que el que proporciona la implementación predeterminada de Equals en ValueType.

  • Si reemplaza el método Equals y el lenguaje admite la sobrecarga de operadores, debe sobrecargar el operador de igualdad correspondiente al tipo de valor.

Las instrucciones siguientes sirven para implementar un tipo de referencia:

  • Considere la posibilidad de reemplazar Equals en un tipo de referencia si la semántica del tipo se basa en el hecho de que este tipo representa algún valor o algunos valores.

  • La mayoría de los tipos de referencia no deben sobrecargar el operador de igualdad, aunque reemplacen el método Equals. No obstante, cuando se implemente un tipo de referencia destinado a tener semántica de valor, como un tipo de número complejo, debe reemplazarse el operador de igualdad.

Ejemplos

En el siguiente ejemplo de código se compara la instancia actual con otro objeto.

Visual Basic

Imports System
Imports System.IO

Class Program
    Public Shared Sub Main(ByVal args As String())
        Dim Obj1 As New Object()
        Dim Obj2 As New Object()
        Console.WriteLine(Obj1.Equals(Obj2))
        Obj2 = Obj1
        Console.WriteLine(Obj1.Equals(Obj2))
    End Sub
End Class

'This example produces the following output:
'False
'True


C#

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
 */


Visual C++

using namespace System;

void main()
{
    Object^ Obj1 = gcnew Object;
    Object^ Obj2 = gcnew Object;
    Console::WriteLine(Obj1->Equals(Obj2));
    Obj2 = Obj1;
    Console::WriteLine(Obj1->Equals(Obj2));
};

/* This example produces the following output:

False
True
 */


El siguiente ejemplo muestra una clase Point que reemplaza el método Equals para proporcionar igualdad de valores y una clase Point3D, que se deriva de Point. Dado que el reemplazo de Equals por parte de Point es el primero en la cadena de herencia para introducir la igualdad de valores, no se invoca el método Equals de la clase base (que se hereda de Object y comprueba la igualdad referencial). No obstante, Point3D.Equals invoca a Point.Equals porque Point implementa Equals de forma que se proporciona igualdad de valores.

Visual Basic

Imports System

Class Point
    Inherits Object
    Protected x, y As Integer

    Public Sub New() 
        Me.x = 0
        Me.y = 0
    End Sub 'New

    Public Sub New(ByVal X As Integer, ByVal Y As Integer) 
        Me.x = X
        Me.y = Y
    End Sub 'New

    Public Overrides Function Equals(ByVal obj As Object) As Boolean 
        'Check for null and compare run-time types.
        If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then
            Return False
        End If
        Dim p As Point = CType(obj, Point)
        Return x = p.x AndAlso y = p.y
    End Function 'Equals

    Public Overrides Function GetHashCode() As Integer 
        Return x ^ y
    End Function 'GetHashCode
End Class 'Point

Class Point3D
    Inherits Point
    Private z As Integer

    Public Sub New(ByVal X As Integer, ByVal Y As Integer, ByVal Z As Integer) 
        Me.x = X
        Me.y = Y
        Me.z = Z
    End Sub 'New

    Public Overrides Function Equals(ByVal obj As Object) As Boolean 
        Return MyBase.Equals(obj) AndAlso z = CType(obj, Point3D).z
    End Function 'Equals

    Public Overrides Function GetHashCode() As Integer 
        Return MyBase.GetHashCode() ^ z
    End Function 'GetHashCode
End Class 'Point3D

Class [MyClass]
    Public Shared Sub Main() 
        Dim point2D As New Point(5, 5)
        Dim point3Da As New Point3D(5, 5, 2)
        Dim point3Db As New Point3D(5, 5, 2)

        If Not point2D.Equals(point3Da) Then
            Console.WriteLine("point2D does not equal point3Da.")
        End If
        If Not point3Db.Equals(point2D) Then
            Console.WriteLine("Likewise, point3Db does not equal point2D.")
        End If
        If point3Da.Equals(point3Db) Then
            Console.WriteLine("However, point3Da equals point3Db.")
        End If

    End Sub 'Main 
End Class '[MyClass]
' ----------------------------------
' Output should be:
' 
' point2D does not equal point3Da.
' Likewise, point3Db does not equal point2D.
' However, point3Da equals point3Db.


C#

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.


Visual C++

using namespace System;
ref class Point: public Object
{
protected:
   int x;
   int y;

public:
   Point()
   {
      this->x = 0;
      this->y = 0;
   }

   Point( int X, int Y )
   {
      this->x = X;
      this->y = Y;
   }

   virtual bool Equals( Object^ obj ) override
   {

      //Check for null and compare run-time types.
      if ( obj == nullptr || GetType() != obj->GetType() )
            return false;

      Point ^ p = dynamic_cast<Point^>(obj);
      return (x == p->x) && (y == p->y);
   }

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

};

ref class Point3D: public Point
{
private:
   int z;

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

   virtual bool Equals( Object^ obj ) override
   {
      return Point::Equals( obj ) && z == (dynamic_cast<Point3D^>(obj))->z;
   }

   virtual int GetHashCode() override
   {
      return Point::GetHashCode() ^ z;
   }

};


El método Point.Equals comprueba que el argumento obj no es null y que hace referencia a una instancia del mismo tipo que este objeto. Si alguna de las comprobaciones no es satisfactoria, el método devuelve false.

El método Equals utiliza GetType para determinar si los tipos en tiempo de ejecución de los dos objetos son idénticos. Conviene señalar que typeof no se utiliza aquí porque devuelve el tipo estático. Si el método utilizó una comprobación de la forma obj is Point, la comprobación devolverá true en los casos en los que obj sea una instancia de una clase derivada de Point, aunque obj y la instancia actual no tengan el mismo tipo en tiempo de ejecución. Una vez que se haya comprobado que ambos objetos son del mismo tipo, el método convierte obj en el tipo Point y devuelve el resultado de comparar las variables de instancia de los dos objetos.

En Point3D.Equals, el método Equals heredado se invoca antes que nada; el método Equals heredado comprueba si obj no es null, si obj es una instancia de la misma clase que este objeto y si las variables de instancia heredadas coinciden. Sólo cuando el Equals heredado devuelva true el método comparará las variables de instancia introducidas en la clase derivada. Concretamente, la conversión en Point3D no se ejecuta salvo que se haya determinado que obj sea de tipo Point3D o una clase derivada de Point3D.

En el ejemplo anterior, operator == (operador de igualdad) se utiliza para comparar las variables de instancia individuales. En algunos casos, debe utilizarse el método Equals para comparar variables de instancia en una implementación de Equals, tal y como se muestra en el siguiente ejemplo de código.

Visual Basic

Imports System

Class Rectangle
    Private a, b As Point

    Public Sub New(ByVal upLeftX As Integer, ByVal upLeftY As Integer, _
                   ByVal downRightX As Integer, ByVal downRightY As Integer) 
        Me.a = New Point(upLeftX, upLeftY)
        Me.b = New Point(downRightX, downRightY)
    End Sub 'New

    Public Overrides Function Equals(ByVal obj As [Object]) As Boolean 
        ' Performs an equality check on two rectangles (Point object pairs).
        If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then
            Return False
        End If
        Dim r As Rectangle = CType(obj, Rectangle)
        'Uses Equals to compare variables.
        Return a.Equals(r.a) AndAlso b.Equals(r.b)
    End Function 'Equals

    Public Overrides Function GetHashCode() As Integer 
        Return a.GetHashCode() ^ b.GetHashCode()
    End Function 'GetHashCode
End Class 'Rectangle

' Class Point added for clean compile

Class Point
    Private x As Integer
    Private y As Integer

    Public Sub New(ByVal X As Integer, ByVal Y As Integer) 
        Me.x = X
        Me.y = Y
    End Sub 'New

    Public Overrides Function Equals(ByVal obj As [Object]) As Boolean 
        ' Performs an equality check on two points (integer pairs).
        If obj Is Nothing OrElse Not [GetType]().Equals(obj.GetType()) Then
            Return False
        End If
        Dim p As Point = CType(obj, Point)
        Return x = p.x AndAlso y = p.y

    End Function 'Equals

    Public Overrides Function GetHashCode() As Integer 
        Return x.GetHashCode() ^ y.GetHashCode()
    End Function 'GetHashCode
End Class 'Point 


Class [MyClass]
    Public Shared Sub Main() 
        Dim r1 As New Rectangle(0, 0, 100, 200)
        Dim r2 As New Rectangle(0, 0, 100, 200)
        Dim r3 As New Rectangle(0, 0, 150, 200)

        If r1.Equals(r2) Then
            Console.WriteLine("Rectangle r1 equals rectangle r2!")
        End If
        If Not r2.Equals(r3) Then
            Console.WriteLine("But rectangle r2 does not equal rectangle r3.")
        End If
    End Sub 'Main
End Class '[MyClass]
' ------------------------------
' Output should be:
' Rectangle r1 equals rectangle r2!
' But rectangle r2 does not equal rectangle r3.


C#

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.


Visual C++

ref class Rectangle
{
private:
   Point^ a;
   Point^ b;

public:
   Rectangle( int upLeftX, int upLeftY, int downRightX, int downRightY )
   {
      this->a = gcnew Point( upLeftX,upLeftY );
      this->b = gcnew Point( downRightX,downRightY );
   }

   virtual bool Equals( Object^ obj ) override
   {

      // Performs an equality check on two rectangles (Point object pairs).
      if ( obj == nullptr || GetType() != obj->GetType() )
            return false;

      Rectangle^ r = dynamic_cast<Rectangle^>(obj);

      //Uses Equals to compare variables.
      return a->Equals( r->a ) && b->Equals( r->b );
   }

   virtual int GetHashCode() override
   {
      return a->GetHashCode() ^ b->GetHashCode();
   }

};


En algunos lenguajes, como C# y Visual Basic, la sobrecarga de operadores se admite. Cuando un tipo sobrecarga el operador de igualdad, también debe reemplazar el método Equals para ofrecer la misma funcionalidad. Esto se consigue normalmente escribiendo el método Equals en términos del operador de igualdad sobrecargado, como en el siguiente ejemplo de código.

Visual Basic

Public Structure Complex
    Public re, im As Double

    Public Overrides Function Equals(ByVal obj As [Object]) As Boolean 
        Return TypeOf obj Is Complex AndAlso Me = CType(obj, Complex)
    End Function 

    Public Overrides Function GetHashCode() As Integer 
        Return re.GetHashCode() ^ im.GetHashCode()
    End Function 

    Public Shared Operator = (x As Complex, y As Complex) As Boolean
       Return x.re = y.re AndAlso x.im = y.im
    End Operator 

    Public Shared Operator <> (x As Complex, y As Complex) As Boolean
       Return Not (x = y)
    End Operator  
End Structure

Class Example
   Public Shared Sub Main() 
      Dim cmplx1, cmplx2 As Complex

      cmplx1.re = 4.0
      cmplx1.im = 1.0

      cmplx2.re = 2.0
      cmplx2.im = 1.0

      If cmplx1 <> cmplx2 Then
         Console.WriteLine("The two objects are not equal.")
      End If
      If Not cmplx1.Equals(cmplx2) Then
         Console.WriteLine("The two objects are not equal.")
      End If

      cmplx2.re = 4.0

      If cmplx1.Equals(cmplx2) Then
         Console.WriteLine("The two objects are now equal!")
      End If
      If cmplx1 = cmplx2 Then
         Console.WriteLine("The two objects are now equal!")
      End If
   End Sub
End Class 
' 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!


C#

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!


Visual C++

using namespace System;
public value struct Complex
{
public:
   double re;
   double im;
   virtual bool Equals( Object^ obj ) override
   {
      return (dynamic_cast<Complex^>(obj) != nullptr) && (*this == *dynamic_cast<Complex^>(obj));
   }

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

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

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

int main()
{
   Complex cmplx1;
   Complex 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!


Dado que Complex es un struct de C# (un tipo de valor), no admite la acción de derivar; por lo tanto, el método Equals no necesita comparar los resultados de GetType para cada objeto; en su lugar se puede utilizar el operador is para comprobar el tipo del parámetro obj.

Información de versión

.NET Framework

Compatible con: 4, 3.5, 3.0, 2.0, 1.1, 1.0

.NET Framework Client Profile

Compatible con: 4, 3.5 SP1

Compatible con:
Plataformas

Windows 7, Windows Vista SP1 o posterior, Windows XP SP3, Windows XP SP2 x64 Edition, Windows Server 2008 (no se admite Server Core), Windows Server 2008 R2 (se admite Server Core con SP1 o posterior), Windows Server 2003 SP2

.NET Framework no admite todas las versiones de todas las plataformas. Para obtener una lista de las versiones compatibles, vea Requisitos de sistema de .NET Framework.
Vea también

Referencia

Historial de cambios

Fecha

Historial

Motivo

Octubre de 2010

Revisado el último ejemplo.

Comentarios de los clientes.