2010-12-28 8 views
6

Los MSDN Guidelines for Overloading Equals() and Operator == estatales:Anulación del operador == en tipos no inmutables

Por defecto, el operador == pruebas para igualdad de referencia mediante la determinación de si dos referencias indican el mismo objeto, por lo que los tipos de referencia no necesita para implementar operator == para obtener esta funcionalidad. Cuando un tipo de es inmutable, es decir, los datos incluidas en la instancia no se puede cambiado, la sobrecarga == operador comparar el valor de igualdad en lugar de la igualdad de referencia puede ser útil porque, como objetos inmutables, que pueden considerarse la igual que tienen el mismo valor. Anulación operador == en tipos no inmutables es no recomendado.

¿Alguien puede explicar el razonamiento detrás del negrita?

EDITAR - Además, es relevante para esta directriz sólo el operador ==, o está destinado para el método Equals así?

Respuesta

16

Mi conjetura sería hacer que las cosas funcionen como los tipos incorporados en .NET do, es decir, que == debería funcionar como igualdad de referencia siempre que sea posible, y que Equals debería funcionar como valor de igualdad cuando sea posible. Considere la diferencia real entre == y Equals:

object myObj = new Integer(4); 
object myObj2 = new Integer(4); 

//Note that == is only called if the ref'd objects are cast as a type 
//overloading it. 
myObj == myObj2; //False (???) 
myObj.Equals(myObj2); //True (This call is virtual) 

//Set the references equal to each other -- note that the operator== 
//comparison now works. 
myObj2 = myObj; 
myObj == myObj2; //True 
myObj.Equals(myObj2); //True 

Este comportamiento es por supuesto incoherente y confuso, sobre todo a los nuevos programadores - pero demuestra la diferencia entre las comparaciones de referencia y comparaciones de valor.

Si sigue esta guía de MSDN, estará siguiendo la guía tomada por las clases importantes, como la cadena. Básicamente, si una comparación usando == tiene éxito, el programador sabe que esa comparación siempre tendrá éxito, siempre y cuando las referencias involucradas no se asignen a objetos nuevos. El programador no tiene que preocuparse por el contenido de los objetos son diferentes, porque nunca serán diferentes:

//Mutable type 
var mutable1 = new Mutable(1); 
var mutable2 = mutable1; 
mutable1 == mutable2; //true 
mutable1.MutateToSomethingElse(56); 
mutable1 == mutable2; //still true, even after modification 
//This is consistent with the framework. (Because the references are the same, 
//reference and value equality are the same.) Consider if == were overloaded, 
//and there was a difference between reference and value equality: 

var mutable1 = new Mutable(1); 
var mutable2 = new Mutable(1); 
mutable1 == mutable2; //true 
mutable1.MutateToSomethingElse(56); 
mutable1 == mutable2; //oops -- not true anymore 
//This is inconsistent with, say, "string", because it cannot mutate. 

Todo se reduce a que no hay ninguna razón técnica real para la directriz - es sólo para ser coherentes con el resto de las clases en el marco.

+1

+1 esta es claramente la respuesta –

+0

Muy bien pensada, buena respuesta. – jason

0

Supongamos que tiene un tipo mutable A y crea un conjunto u objetos de tipo A. Agregar un objeto al conjunto debería fallar si este objeto ya existe en el conjunto.

Ahora supongamos que agrega un objeto al conjunto y luego cambia sus propiedades para que se convierta en igual a otro objeto en el conjunto. Ha creado un estado ilegal, donde hay dos objetos en el conjunto que son iguales.

+0

Pero el uso de 'Equals' en lugar de' == 'no soluciona este problema. –

+0

Otra directriz es anular siempre '==' y 'Igual()' juntas. Y 'getHashCoe()' también. –

+0

En realidad lo hace - Equal es semánticamente diferente. Lea la documentación de ambos para ver la diferencia. – TomTom

Cuestiones relacionadas