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?
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.
See more on this question at Stackoverflow