参考参数的IL差异

时间:2019-05-01 07:42:17

标签: c# cil ref

我试图理解在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的左侧有关吗?

1 个答案:

答案 0 :(得分:0)

IL_0001: ldarg.0处的存储操作将消耗在IL_0006: stind.i4处加载的地址。

msdn告诉我们有关stind.i4操作码的信息:

  

按顺序排列的堆栈过渡行为是:

     
      
  1. 地址被压入堆栈。

  2.   
  3. 一个值被压入堆栈。

  4.   
  5. 值和地址从堆栈中弹出;值存储在地址中。

  6.   

https://docs.microsoft.com/de-de/dotnet/api/system.reflection.emit.opcodes.stind_i4?view=netframework-4.8