2012-01-20 14 views
10

Me pregunto por qué la salida del código dado (ejecutarlo en LINQPad)método implícito Gotcha conversión grupo

void Main() { 
    Compare1((Action)Main).Dump(); 
    Compare2(Main).Dump(); 
} 

bool Compare1(Delegate x) { 
    return x == (Action)Main; 
} 

bool Compare2(Action x) { 
    return x == Main; 
} 

es siempre:

False 
True 

he esperado ingenuamente que sea True en ambos casos.

+1

Cambiando 'Compare1' para usar' return x == (Delegate) (Action) Main; 'lo devuelve' true'. Sin embargo, no estoy seguro de por qué. – Joey

+0

FYI: Hice una pregunta relativa aquí: http: //stackoverflow.com/questions/8939350/implicit-method-group-conversion-gotcha-part-2 –

Respuesta

9

Así es como se ve cuando se compila en IL y luego se vuelve a descompilar en C#. Tenga en cuenta que en ambos casos hay new Action(Main) - un nuevo objeto de referencia (delegado) con un puntero al método real almacenado en el interior.

private static void Main() 
{ 
    Program.Compare1(new Action(Program.Main)).Dump(); 
    Program.Compare2(new Action(Program.Main)).Dump(); 
    Console.ReadLine(); 
} 

private static bool Compare1(Delegate x) 
{ 
    return x == new Action(Program.Main); 
} 

private static bool Compare2(Action x) 
{ 
    return x == new Action(Program.Main); 
} 

Si a continuación, echamos un vistazo a CIL, los antiguos usos ceq (comparación de referencia) y los segundos usos call bool [mscorlib]System.Delegate::op_Equality(class [mscorlib]System.Delegate, class [mscorlib]System.Delegate) para comparar los delegados.

Primero devuelve false porque las acciones que envuelven a sus delegados son dos objetos de referencia distintos.

Segundo devuelve true como el operador de igualdad implementado en la clase Delegate compara objetivos reales dentro de contenedores (acciones).

7

El resultado false está relacionado con el hecho de que el Comparación1() método realiza la comparación de referencia en dos objeto diferente (compilador muestra el aviso correspondiente):

IL_0001: ldarg.0 
IL_0002: ldnull 
IL_0003: ldftn  instance void ConsoleApplication1.Test::Main() 
IL_0009: newobj  instance void [System.Core]System.Action::.ctor(object, 
                    native int) 
IL_000e: ceq <<reference comparison 

Puede evitar el problema mediante el código siguiente:

bool Compare1(Delegate x) { 
    return x == (Delegate)((Action)Main); 
} 
Cuestiones relacionadas