It is there to implement a promise made in the C# language specification. Which says that it is not legal to call an instance method of a class through a null reference. This may sound like an obvious feature, but it is not actually that common in OOP languages. In particular the C++/CLI compiler doesn't have it. And the CLI spec doesn't have it. An unmanaged language like C++ doesn't have it.
It even comes to a good end, sometimes, when the instance method doesn't use any non-static class members. Such a method should of course be static but that is not required or enforced.
The C# requirement is very nice, it makes a NullReferenceException
much easier to diagnose. Since they are generated at the call site instead of inside the instance method., it clarifies that the object reference is null. Figuring out that the this reference is null inside a method is kinda difficult, especially since you can't see it. Further complicated by the address not actually being null, accessing a field of a class will generate an address that's offset from 0. Which in turn is unsafe if the object is humongous, more than 64 kilobytes. Accessing a field at the end of such a big object won't necessarily generate a processor exception, you'll just read random junk. Or corrupt memory if you write it.
So the C# team looked for a cheap way to implement the null test. And found one in the callvirt
IL instruction. Which, unlike call
, does promise an exception in the CLI specification. A very cheap test, it requires only a single machine code instruction. And doesn't require a branch, that's very expensive if the processor's branch prediction logic guesses wrong.
You now also know why String.Equals() contains this bit of mysterious code:
public override bool Equals(Object obj) {
if (this == null)
throw new NullReferenceException();
// etc...
}