我试图理解在IL级别处理通过引用传递的参数和值之间的区别。
这是C#中的两种方法
public static void TestRef(ref int x)
{
x++;
}
public static void Test(int x)
{
x++;
}
按值传递的IL如下,我知道它先加载arg,然后再加载int常量1并将其添加并填充回堆栈中。
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.1
IL_0003: add
IL_0004: starg.s x
IL_0006: ret
通过引用传递的方法的IL:
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldarg.0
IL_0003: ldind.i4
IL_0004: ldc.i4.1
IL_0005: add
IL_0006: stind.i4
IL_0007: ret
我不明白为什么有两个ldarg.0
语句。我假设IL_0002 / 3只是加载参数地址,然后加载该地址的参数值。
那IL_0001呢?与x =x+1
的左侧有关吗?
答案 0 :(得分:0)
在IL_0001: ldarg.0
处的存储操作将消耗在IL_0006: stind.i4
处加载的地址。
msdn告诉我们有关stind.i4
操作码的信息:
按顺序排列的堆栈过渡行为是:
地址被压入堆栈。
一个值被压入堆栈。
值和地址从堆栈中弹出;值存储在地址中。