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

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?

Jon Skeet
people
quotationmark

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.

people

See more on this question at Stackoverflow