I was looking through What's the strangest corner case you've seen in C# or .NET?, and this code made me think a little:
public class Program
{
delegate void HelloDelegate(Strange bar);
[STAThread()]
public static void Main(string[] args)
{
Strange bar = null;
var hello = new DynamicMethod("ThisIsNull",
typeof(void), new[] { typeof(Strange) },
typeof(Strange).Module);
ILGenerator il = hello.GetILGenerator(256);
il.Emit(OpCodes.Ldarg_0);
var foo = typeof(Strange).GetMethod("Foo");
il.Emit(OpCodes.Call, foo);
il.Emit(OpCodes.Ret);
var print = (HelloDelegate)hello.CreateDelegate(typeof(HelloDelegate));
print(bar);
Console.ReadLine();
}
internal sealed class Strange
{
public void Foo()
{
Console.WriteLine(this == null);
}
}
}
I do understand what the code does, but I do not understand why it works. Isn't that like doing null.Foo()
? It works as if Foo()
is static, and this is being called instead: Strange.Foo();
.
Would you please tell me what I am missing?
this
is implemented as a normal parameter; your code simply passes null
as this parameter.
The only reason that this would normally throw a NullReferenceException
is that methods are usually called using the CallVirt
instruction, which does a vtable lookup on the this
parameter and throws if it's null.
If you use call
, the method will execute perfectly fine even if this
is null, although the method itself will likely end up throwing later.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With