Pregunta

Considere este fragmento C #:

static string input = null;
static string output = null;

static void Main(string[] args)
{
     input = "input";
     output = CallMe(input);
}

public static string CallMe(string input)
{
     output = "output";
     return output;
}

Dissassembling usando shows Reflector:

.method private hidebysig static void Main(string[] args) cil managed
    {
        .entrypoint
        .maxstack 8
        L_0000: nop 
        L_0001: ldstr "input"
        L_0006: stsfld string Reflector_Test.Program::input
        L_000b: ldsfld string Reflector_Test.Program::input
        L_0010: call string Reflector_Test.Program::CallMe(string)
        L_0015: stsfld string Reflector_Test.Program::output
        L_001a: ret 
    }

 .method public hidebysig static string CallMe(string input) cil managed
    {
        .maxstack 1
        .locals init (
            [0] string CS$1$0000)
        L_0000: nop 
        L_0001: ldstr "output"
        L_0006: stsfld string Reflector_Test.Program::output
        L_000b: ldsfld string Reflector_Test.Program::output
        L_0010: stloc.0 
        L_0011: br.s L_0013
        L_0013: ldloc.0 
        L_0014: ret 
    }

La pieza que me intriga es:

L_0010: stloc.0 
L_0011: br.s L_0013
L_0013: ldloc.0 

Almacena el artículo, ramas a la línea siguiente (lo que habría sido ejecutado de todas formas) y luego se carga de nuevo.

¿Hay una razón para esto?

¿Fue útil?

Solución

Esto sólo ocurre en la depuración, no en su liberación. Sospecho que su para ayudar durante la depuración. Tal vez le permite al mandril puntos de interrupción mediados declaración y ve el valor de retorno.

Tenga en cuenta la versión de lanzamiento tiene IL mucho más concisa:

.method private hidebysig static void Main(string[] args) cil managed
{
    .maxstack 8
    L_0000: ldstr "input"
    L_0005: stsfld string Reflector_Test.Program::input
    L_000a: ldsfld string Reflector_Test.Program::input
    L_000f: call string Reflector_Test.Program::CallMe(string)
    L_0014: stsfld string Reflector_Test.Program::output
    L_0019: ret 
}




.method public hidebysig static string CallMe(string input) cil managed
{
    .maxstack 8
    L_0000: ldstr "output"
    L_0005: stsfld string Reflector_Test.Program::output
    L_000a: ldsfld string Reflector_Test.Program::output
    L_000f: ret 
}

Otros consejos

Mi conjetura es que se trata de código reutilizable para ejecutar una instrucción de retorno, el compilador ejecuta un salto incondicional a la última línea, y carga el valor de retorno en un registro antes de ejecutar el ret. El JIT optimizará mejor, creo que el compilador no se molesta en hacer cualquier optimizaciones.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top