考虑一下这个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;
}
使用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
}
令我困惑的是:
L_0010: stloc.0
L_0011: br.s L_0013
L_0013: ldloc.0
它存储项目,分支到下一行(无论如何都会执行),然后再次加载。
这是否有原因?
答案 0 :(得分:7)
这只发生在Debug中,而不是发布中。我怀疑它在调试期间有所帮助。它可能允许你在语句中查找断点并查看返回值。
请注意,发布版本有更简洁的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
}
答案 1 :(得分:0)
我的猜测是,这是用于执行return语句的样板代码,编译器执行无条件跳转到最后一行,并在执行ret
之前将返回值加载到寄存器中。 JIT会更好地优化它,我认为编译器不会做任何优化。