用于访问只读字段的 MSIL 代码生成 ldarg.0

本文关键字:代码生成 ldarg MSIL 访问 读字段 用于 | 更新日期: 2023-09-27 18:31:57

我在 C# 中有一个简单的方法可以访问只读字段:

IL_0024:  ldarg.0
IL_0025:  ldfld      string MyAssembly.MyClass.TestClass::A

我的自然假设是,这用于在访问成员字段时加载"this"引用,并且此问题也证实了:为什么在 MSIL 中调用字段之前必须执行 ldarg.0?

但是,ldarg 的文档提到它用于加载传递给方法的参数。

这种行为的正确解释是什么?以及如何区分加载"this"引用和将第一个形式参数加载到IL中的方法?

用于访问只读字段的 MSIL 代码生成 ldarg.0

两者都是正确的:)

this值作为第一个"不可见"参数传递给实例方法,因此在实例方法中,ldarg.0是"加载this值"。

如果编写使用不同参数的方法,则可以看到差异。例如:

static void StaticMethod(int x)
{
    // This uses ldarg.0
    Console.WriteLine(x);
}
void InstanceMethod(int x)
{
    // This uses ldarg.1
    Console.WriteLine(x);
}

以及如何区分加载"this"引用和将第一个形式参数加载到 IL 中的方法?

通过检查上述内容,基本上 - 如果它是一个实例方法,那么ldarg.0加载隐式this值。否则,它将加载第一个形式参数值。

所有实例方法都采用第一个参数作为类实例本身。这是隐式完成的,因此在调用方法时不必传递它。

鉴于this是一个方法参数,您需要使用 ldarg.0this实例推送到评估堆栈。