Consider this C# snippet:
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 using Reflector shows:
.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 }
The piece that puzzles me is:
L_0010: stloc.0 L_0011: br.s L_0013 L_0013: ldloc.0
It stores the item, branches to the next line (which would have been executed anyway) and then loads it again.
Is there a reason for this?
This only happens in Debug, not in Release. I suspect its to assist during debugging. It perhaps allows you to chuck breakpoints mid statement and see the return value.
Note the release version has much more concise IL: