MSIL code for accessing a readonly field results in ldarg.0

224 Views Asked by At

I have a simple method in C# that accesses a readonly field:

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

My natural assumption was that this is used for loading the "this" reference when accessing member fields, and this question also confirms that: Why do I have to do ldarg.0 before calling a field in MSIL?

However, the documentation for ldarg mentions that it is used for loading parameters passed to the method.

What is the correct explanation for this behaviour? and how can one distinguish between loading the "this" reference and loading the first formal parameter to a method in IL?

2

There are 2 best solutions below

0
On BEST ANSWER

Both are correct :)

The this value is passed as a first "invisible" parameter to instance methods, so in an instance method, ldarg.0 is "load the this value".

You can see the difference if you write a method which uses a different parameter. For example:

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

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

and how can one distinguish between loading the "this" reference and loading the first formal parameter to a method in IL?

By checking the above, basically - if it's an instance method, then ldarg.0 loads the implicit this value. Otherwise, it loads the first formal parameter value.

0
On

All instance methods takes first parameter as the class instance itself. This is done implicitly, so you don't have to pass it when you're calling a method.

Given that this is a method parameter, you need to use ldarg.0 to push the this instance to evaluation stack.