2008-09-22 13 views
48

Entonces, cuando era un novato en comparación con el novato que soy ahora, solía pensar que estas dos cosas eran azúcar sintáctica para el otro, es decir, que el uso uno sobre el otro era simplemente una preferencia personal. Con el tiempo, he llegado a la conclusión de que estos dos no son lo mismo, incluso en una implementación predeterminada (ver this y this). Para confundir aún más el asunto, cada uno puede ser anulado/sobrecargado por separado para tener significados completamente diferentes.== frente a Object.Equals (objeto) en .NET

¿Es esto una buena cosa, cuáles son las diferencias, y cuándo/por qué debería usar uno sobre el otro?

Respuesta

17

MSDN tiene descripciones claras y sólidas de ambas cosas.

object.Equals method

operator ==

Overloadable Operators

Guidelines for Overriding Equals() and Operator ==

¿Es esta una buena cosa, ¿cuáles son las diferencias, y cuando/¿por qué debería utilizar uno sobre el otro ?

¿Cómo puede ser "bueno" o "malo"? Un método, otro operador. Si la igualdad de referencia no es suficiente, sobrecargúelos, de lo contrario déjelos como están. Para los tipos primitivos simplemente funcionan fuera de la caja.

+0

Como alguien que entra en los genéricos las diferencias pueden ser enormes cuando las está llamando en cualquier tipo T a ciegas. –

+2

"ciegamente" es una mala práctica para cualquier cosa. si conoce la respuesta a su pregunta, ¿por qué pregunta? – aku

+0

Incluso si conociera una respuesta concreta (que no es así), ¿quizás por la misma razón por la que la gente hace preguntas y se responde a sí misma? Además, ¿cómo puedes hacer algo más por un tipo genérico T? Si comienzas a hacer cosas como if (typeof (T) == typeof (int)), ¿cuál es el punto? –

1

Mi comprensión de los usos de ambos fue esta: use == para igualdad conceptual (en contexto, ¿estos dos argumentos significan lo mismo?), Y .Equals para igualdad concreta (son estos dos argumentos en realidad el exactamente el mismo objeto?).

Editar: artículo enlazado de Kevin Sheffield hace un mejor trabajo de explicar el valor de referencia frente a la igualdad ...

+0

De acuerdo, pero eso suena como una buena regla empírica. –

+0

No es correcto. 'ReferenceEquals' es la prueba de 'identidad' en .Net. Si 'igual' siempre hizo una prueba de identidad, entonces no tendría sentido tener ambos ... – ToolmakerSteve

0

Es posible que desee utilizar .Equals ya que alguien puede venir en otro momento y sobrecargarlos para su clase.

+0

¿Pero no sería eso algo bueno? –

+0

Sí, creo que quise decirlo al revés. –

33
string x = "hello"; 
string y = String.Copy(x); 
string z = "hello"; 

Para probar si x apunta al mismo objeto que y:

(object)x == (object)y // false 
x.ReferenceEquals(y) // false 
x.ReferenceEquals(z) // true (because x and z are both constants they 
         //  will point to the same location in memory) 

Para probar si x tiene el mismo valor de cadena como y:

x == y  // true 
x == z  // true 
x.Equals(y) // true 
y == "hello" // true 

Tenga en cuenta que esto es diferente a Java. En Java no está sobrecargado el operador == por lo que un error común en Java es:

y == "hello" // false (y is not the same object as "hello") 

Para la comparación de cadenas en Java es necesario utilizar siempre .equals()

y.equals("hello") // true 
+2

Para operador de cadena == compara ambas cadenas por contenido. Pero ese no es el caso para otros tipos de referencia – Vaysage

+1

Quiero subrayar lo que Vaysage acaba de decir: Usar "cadena" como ejemplo es ** engañoso ** (o al menos incompleto)) Muestra cómo funcionan las cadenas. Pero la cadena es un ** caso especial **. Para que esta respuesta sea completa, contraste una "cadena" con: (a) un solo carácter, (b) una matriz de caracteres, (c) una "estructura" que contenga varios campos de caracteres, (d) una "clase" que contenga varios campos de caracteres Quizás incluso necesite mostrar (e) una 'clase' que contenga un campo' struct' o que contenga un campo 'character array'. Luego haga varias asignaciones, muestre cuando el resultado sigue siendo 'verdadero'. – ToolmakerSteve

-1

Dos de los tipos más utilizados, String e Int32, implementar tanto operator ==() como Equals() como valor de igualdad (en lugar de igualdad de referencia).Creo que uno puede considerar estos dos ejemplos de definición, por lo que mi conclusión es que tienen idénticos significados. Si Microsoft states otherwise, creo que están causando confusión intencionalmente.

+1

Dentro de .net, los tipos que anulan los operadores de igualdad/desigualdad lo hacen para imponer igualdad de valores, pero C# agrega su propia sobrecarga de operadores de igualdad/desigualdad para verificar la igualdad de referencia de objetos que no incluyen una prueba de igualdad de valores. Personalmente, no me gusta el diseño del lenguaje (vb.net utiliza los operadores 'Is' y' IsNot' para probar la igualdad de referencia; cuando se aplica a tipos de Framework, '=' y '<>' pondrán a prueba la igualdad del valor si compilan en absoluto Sin embargo, no hay nada que impida que un tipo sobrecargue a esos operadores para que signifique algo totalmente diferente. – supercat

9

Dada estado de cuenta actual de Microsoft en operadores de igualdad y ==!=, la conclusión es: ==debe ser sólo azúcar sintáctica para Object.Equals():

¿garantiza que Object.equals y los operadores de igualdad tienen exactamente el mismo semántica

de http://msdn.microsoft.com/en-us/library/vstudio/7h9bszxx(v=vs.110).aspx

Que son distintos, en lugar de solo azúcar, en retrospectiva, parece ser un error en su diseño.

Si quiere estar seguro de que está obteniendo IDENTIDAD comparación (al comparar referencias), entonces use ReferenceEquals en su lugar.

Por desgracia, el manejo de == es tan inconsistente, que normalmente evitar que cuando se manipula de otra persona clases personalizadas, y sólo tiene que utilizar el menos legible Equals(a, b) o ReferenceEquals(a, b), dependiendo de lo que significa que quiero.

En mi humilde opinión, sería mejor para las personas no implementar == y != en absoluto. Simplemente deje .Net predeterminado a Equals y ! Equals, e implemente Equals según corresponda.

Si alguien tiene un razonamiento diferente, me gustaría escucharlo.

(Y sí, esto es realmente confuso, dado que Java existía primero, y usa == para significar ==. Pero es demasiado tarde para modificar .Net para comportarse de esa manera. Y tenemos la declaración de Microsoft para ese efecto, en el enlace anterior).

+0

Agregué otra respuesta que puede cambiar su parecer un poco (no es que me importe su razonamiento). Llamar a '.Equals()' en un nulo objeto (excepción lanzada) vs uso de un operador estático que no requiere ninguno de los operandos para ser instanciado (sin excepción, funciona como se esperaba). – ps2goat

+0

Excelente respuesta. Gracias. En cuanto a su comentario en otra parte de esta página acerca de estar "perplejo de por qué muchos de estas respuestas se vinculan con ese artículo "- es StackOverflow: no se trata de leer la pregunta completa y responderla, se trata de qué tan rápido puede encontrar algo que criticar en la pregunta en sí. De ahí que la persona que critica la pregunta i s en la parte superior de la página y tu respuesta que finalmente aclara este lío en .NET está luchando por obtener votos. :-) –

-1

Operador == e Igual() son los mismos mientras comparamos valores en lugar de referencias. La salida de ambos son los mismos ver el ejemplo a continuación.

Ejemplo

static void Main() 
    { 
     string x = " hello"; 
     string y = " hello"; 
     string z = string.Copy(x); 
     if (x == y) 
     { 
      Console.WriteLine("== Operator"); 
     } 
     if(x.Equals(y)) 
     { 
      Console.WriteLine("Equals() Function Call"); 
     } 
     if (x == z) 
     { 
      Console.WriteLine("== Operator while coping a string to another."); 
     } 
     if (x.Equals(y)) 
     { 
      Console.WriteLine("Equals() Function Call while coping a string to another."); 
     } 
    } 

Salida:

== Operator 
    Equals() Function Call 
    == Operator while coping a string to another. 
    Equals() Function Call while coping a string to another. 
3

que iba a publicar esto como un comentario sobre la respuesta aceptada, pero creo que esto merece tenerse en cuenta al determinar qué ruta para tomar.

dotnetfiddle: https://dotnetfiddle.net/gESLzO

código de violín:

Object a = null; 
    Object b = new Object(); 

    // Ex 1 
    Console.WriteLine(a == b); 
    // Ex 2 
    Console.WriteLine(b == a); 

    // Ex 3  
    Console.WriteLine(b.Equals(a)); 
    // Ex 4 
    Console.WriteLine(a.Equals(b)); 

Los 3 primeros ejemplos WriteLine funcionarán, pero el cuarto emite una excepción.1 y 2 usan ==, que es un método estático que no requiere la instancia de ningún objeto.

El ejemplo 3 funciona porque se crea una instancia de b.

El ejemplo 4 falla porque a es null, y por lo tanto no se puede invocar un método en un objeto nulo.

Como trato de codificar de la forma más perezosa posible, utilizo ==, especialmente cuando trabajo con escenarios donde cualquiera de los objetos (o ambos) puede ser nulo. Si no lo hiciera, primero tendría que hacer una comprobación nula antes de poder llamar al .Equals().

+0

Tenga en cuenta que esto también ocurre con las cadenas. Y, por supuesto, el operador podría ser anulado, pero la esencia de esta respuesta es que los operadores son estáticos y no requieren instancias no nulas para ninguno de los operandos. – ps2goat

Cuestiones relacionadas