Diferencia entre el operador == y el método Equals() en C#

C# es un bonito lenguaje que soporta operator overloading (sobrecarga de operadores) entre otras cosas. También tiene en la clase Object, de la cual heredan todas las otras clases, un método llamado Equals.

El problema que me surgió hoy, fue que necesitaba utilizar el método IList.Remove() pasándole un objeto pero para mi sorpresa no eliminaba nada. Entonces comenzando a investigar encontré el método Equals() y la sobrecarga del operador == y estas son las conclusiones a las que llegué.

Tanto Equals() como operator== tienen por default la misma implementación. O sea las siguientes expresiones son equivalentes, si no redefino ni el método Equals ni el operador igual.

o1  == o2;
o1.Equals(o2);

¿Y como es la comparación que realizan? Simplemente una comparación de referencias (punteros para los mas vejetes como yo) Si dos objetos representan lo mismo, pero son instancias diferentes, y no sobrecarga ni el opeardor == ni Equals, entonces en cualquier comparación serán diferentes.

Tal vez con un ejemplo se aprecie mejor.Imaginemos que tenemos la clase NumeroComplejo que su constructor requiere dos parámetros: el primero la parte real, y el segundo la parte imaginaria. Entonces el siguiente código dirá dos veces que son números diferentes a pesar de ser conceptualmente el mismo numero.

NumeroComplejo num1 = new NumeroComplejo(1,2);
NumeroComplejo num2 = new NumeroComplejo(1,2);

Console.WriteLine(num1 == num2);
Console.WriteLine(num1.Equals(num2));

Esto se debe a que tanto == como Equals comparan la instancia, sin saber nada de su contenido. Ni siquiera hacen una comparación bit a bit, así que como son objeto diferentes, la comparación dice que lo son.

Obviamente, a nosotros nos convendría que digan que son iguales, no es muy intuitivo ver que código que básicamente dice if(1==1) no se ejecute, o en mi caso, sabiendo que una lista tenía un objeto especifico, llamar al método Remove con un objeto conceptualmente igual y que no elimine nada.

Entonces. ¿Que método debía sobrecargar? En algunos lugares leí que todos, pero no me convencía ese enfoque. Después de todo alguna diferencia deben tener, sino no tendría sentido que existan los dos. Por tal motivo seguí investigando y encontré en el lugar mas obvio, la msdn de microsoft, algunos indicios que me indicaron lo siguiente.

  1. Ni microsoft sabe bien la diferencia
  2. Si es un tipo de valor, efectivamente recomiendan sobrecargar todos
  3. Si es un tipo de referencia, se debe sobrecargar Equals
  4. Todos concuerdan que si se redefine Equals, hay que sobrecargar GetHashCode, y si se redefine el operador == se debe sobrecargar el operador !=

O sea, cuando la clase es un numero complejo, o algo en que haga sentido sumar, restar y operar en general, entonces debería sobrecargar todos los operadores porque representa un valor… en cambio si fuera un objeto de clase Persona, lo correcto sería sobrecargar solo Equals() y utilizar, asimismo Equals() cuando se quieren comparar por su valor.

Admito que es una linea bastante delgada, pero creo que esa es la idea, lo cual no sería raro ya que se parece mucho también a la misma dualidad que hay en Java.

En fin, mi caso puntual hoy era un objeto de clase Requerimiento, por lo cual redefiní el método Equals() y magicamente mi IList comenzó a eliminar objetos. Lo cual significa que esta implementada usando el método Equals en lugar del operador== y solo espero todas las demás clases tengan el mismo comportamiento.


2 Responses to “Diferencia entre el operador == y el método Equals() en C#”

  1. Muchas gracias por esto, la verdad que me re ayudo, me estaba volviendo loco buscando la solucion, lo mas gracioso de todo es que estaba intentando de hacer exactamente lo mismo que vos, pero me rasque tanto la cabeza pensando porque no funcionaba y tu pagina salto entre las primeras del google
    nuevamente muchisimas gracias!

  2. Muchísimas gracias, me fue muy útil !!! 😀

Discussion Area - Leave a Comment