C# compiler Fails to Fail-Fast

If title didn’t made sense,  I believe at least the post will 🙂

When you invoke a method on a null instance in  C# NullReferenceException will be thrown unlike C++/CLI which allows instance methods to be called with null references.

C# compiler does this with the help of callvirt opcode. As we saw earlier that the compiler emits call opcode when it can prove that the object reference is not null.

Compiler is trying to be smart and optimizes the callvirt to call opcode as we saw in my last post. I agree; compiler is smart, but not smart enough.

Yeah, compiler made a brave assumption that new operator will never return null. But that’s a false assumption. New operator returns null in this corner case.

Consider my following contrived example:

Clearly the above code shows that the code explodes in middle of the method(where this pointer is dereferenced) with NullReferenceException and not at the very beginning of the method call itself.

The C# compiler failed to Fail Fast and thus the title 🙂



C# compiler doesn’t always emits a virtual call (callvirt)

MSIL provides two ways to call a method in IL level with opcodes call and callvirt respectively.

In a nutshell call opcode calls the method with early binding where as callvirt makes the late bound call(method will be chosen at runtime rather than compile time).

Apart from the early/late binding difference, callvirt also checks if the instance in which the method is being called is null, if so –It will throw NullReferenceException.

If you do a web search you could easily reach some blog posts, forums which says that C# compiler  always emits callvirt for even non virtual methods. Me too tend to believe that was true; it turns out that it is not.

You have been mislead

Hell no! You have been mislead. Although C# compiler usually emits callvirt for non virtual methods, it does emits call opcode when it can prove that the object reference is not null.

Technically there is no reason for the compiler to emit callvirt for non virtual methods or sealed methods as we already know that late binding isn’t going to make any difference because you can’t override a sealed or non virtual method. But compiler emits callvirt just for the sake of getting free null checks by the runtime.

Why does that matters? Why can’t we allow instance methods to be invoked with null instance? Fail Fast is better than allowing you to call a instance method with null reference and surprising you at some point with NullReferenceException where this reference is accessed.

IL code for the above snippet(only Main method) is as follows

Above snippet shows a case where C# compiler emits a call opcode for instance method.

Yeah C# compiler is being smart[1] here by emitting call opcode because it can prove that the instance can never be null. So that it couldn’t waste the cpu cycles in testing for null which we already know it isn’t.

As soon as I discovered this myself, googling little bit turns out that I’m not the first guy to discover it.

1:C# compiler is smart, but not smart enough.