首页 > 解决方案 > ref 参数的 IL 差异

问题描述

我试图了解通过引用传递的参数和值在 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

标签: c#cilref

解决方案


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

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

堆栈过渡行为,按顺序,是:

  1. 一个地址被压入堆栈。

  2. 一个值被压入堆栈。

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

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


推荐阅读