2009-03-23 6 views
3

Betrachten Sie dieses C# Code-Schnipsel:MSIL: Überflüssig Zweig

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 Reflektor zeigt:

.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 
    } 

Das Stück, das mir ein Rätsel ist:

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

Es das Element speichert, verzweigt zur nächsten Zeile (die sowieso ausgeführt worden wäre) und lädt sie dann erneut.

Gibt es einen Grund dafür?

Antwort

7

Dies geschieht nur in Debug, nicht in Release. Ich vermute, dass es beim Debuggen hilft. Es ermöglicht Ihnen vielleicht, Breakpoints Mid-Anweisung zu chuck und den Rückgabewert zu sehen.

Beachten Sie die Release-Version hat viel prägnanter IL:

.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 
} 
0

Meine Vermutung ist, dass dies für die Ausführung einer return-Anweisung Standardcode ist, führt der Compiler einen unbedingten Sprung in die letzte Zeile, und lädt die Rückkehr Wert in ein Register vor der Ausführung der ret. Das JIT wird es besser optimieren, ich denke, der Compiler macht keine Optimierungen.

+0

Es tut im Freigabemodus, siehe meine Antwort –