2011-03-01 12 views
6

Teniendo en cuenta estas dos afirmaciones ...¿Cuál es la diferencia entre usar el operador == y el método Equals en un tipo booleano encuadrado?

((object)false) == ((object)false) 
((object)false).Equals((object)false) 

La primera instrucción devuelve falso. La segunda declaración devuelve verdadero.

Entiendo por qué la primera declaración devuelve falso: cuando el booleano está encuadrado, se convierte en un tipo de referencia y las dos referencias no son iguales. Pero, ¿por qué/cómo el segundo enunciado resulta verdadero?

Respuesta

8

Porque todavía está llamando al método polimórfico Equals, básicamente. código

la muestra a muestra con un tipo diferente: "! Foo.Equals llamados"

using System; 

struct Foo 
{ 
    public override bool Equals(object other) 
    { 
     Console.WriteLine("Foo.Equals called!"); 
     return true; 
    } 

    public override int GetHashCode() 
    { 
     return 1; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     object first = new Foo(); 
     object second = new Foo(); 
     first.Equals(second); 
    } 
} 

que todavía impresiones porque llamar al método Equals en el "cuadro" todavía llama al Foo.Equals.

Ahora == no es anulados, es sobrecargado ... así que si escribir:

object first = ...; 
object second = ...; 
bool same = first == second; 

Eso siempre comparar la identidad de referencia, sin jamás ejecutar cualquier tipo- código específico.

1

Como dijiste, el primer ejemplo verifica si las referencias son iguales, mientras que el segundo busca valores iguales para cada objeto.

De MSDN:

Las siguientes declaraciones deben ser cierto para todas las implementaciones del método Equals. En la lista, x, y y z representan referencias de objeto que no son nulas.

x.Equals (x) devuelve verdadero, excepto en los casos que involucran tipos de coma flotante. Ver IEC 60559: 1989, Aritmética binaria de coma flotante para sistemas de microprocesador.

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

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

If (x.Equals (y) & & y.Equals (z)) devuelve verdadero, entonces x.Equals (z) devuelve verdadero.

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

x.Equals (null) devuelve falso.

1

La sobrecarga del operador no es polimórfica, pero Equals es. Aunque bool tiene una sobrecarga ==, al convertirlo a object está utilizando la implementación de object, que compara la igualdad de referencia. Pero todavía está utilizando la versión bool de Equals.

1

El método Equals es un método virtual que se reemplaza por el tipo Boolean. Por lo tanto, no importa que esté lanzando el bool a un object en la segunda línea; todavía está usando el vtable del tipo para buscar la implementación de Equals proporcionada por el tipo real del objeto (¡eso es polimorfismo para usted!).

El operador == es un operador estático y, por lo tanto, se selecciona la sobrecarga adecuada en tiempo de compilación. El compilador lo ve comparando dos objetos del tipo object con ese operador y así selecciona la sobrecarga (object, object).

Aquí hay un poco estúpido programa para ilustrar la diferencia:

class Thing 
{ 
    public virtual void AnnounceSelf() 
    { 
     Console.WriteLine("I am a Thing."); 
    } 

    public static void AnnounceThing(Thing other) 
    { 
     Console.WriteLine("Here is a Thing."); 
    } 

    public static void AnnounceThing(OtherThing other) 
    { 
     Console.WriteLine("Here is ANOTHER type of Thing."); 
    } 
} 

class OtherThing : Thing 
{ 
    public override void AnnounceSelf() 
    { 
     Console.WriteLine("I am ANOTHER Thing."); 
    } 
} 

class Program 
{ 
    public static void Main() 
    { 
     Thing t = new Thing(); 

     // Outputs "I am a Thing." as expected. 
     t.AnnounceSelf(); 

     // Outputs "Here is a Thing." as expected. 
     Thing.AnnounceThing(t); 

     t = new OtherThing(); 

     // This method is virtual, so even though t is typed as Thing, 
     // the implementation provided by OtherThing will be called; 
     // outputs "I am ANOTHER Thing." 
     t.AnnounceSelf(); 

     // In contrast to above, this method will NOT call the more 
     // specific overload of AnnounceThing (accepting an OtherThing 
     // argument) because t is only typed as Thing, so the compiler 
     // will go with the first; 
     // outputs "Here is a Thing." 
     Thing.AnnounceThing(t); 

     // THIS will output "Here is ANOTHER type of Thing." 
     Thing.AnnounceThing((OtherThing)t); 
    } 
} 
-1

primera es para referencias, segundo es para los valores!

Cuestiones relacionadas