Consider this code:
A a = null;
a.f(); //Will it throw NullReferenceException?
Will the above throw NullReferenceException
?
The answer is : it depends on what f()
is.
This difference leads to a question: how each type of method is implemeneted and viewed by C# compilers? Also, why member method must throw exception even if it doesn't access any member data? It seems that C# compiler makes an assumption in advance that member method will access member data, and so it throws exception if the object is null, as using null object member data cannot be accessed. However, in case of extension method, it postpones this decision till it actually attempts to access member data using null reference, only then it throws exception.
How far my understanding is correct? And if that is so, why this difference?
Yes, I know that if f()
is an extension method, then a.f()
is equivalent to writing AExt.f(a)
, so the latter shouldn't throw exception until a
is used to access member. But my focus is mostly on the compiler implementations (which can implement even member methods in the same way).
Yes, this is how this code behaves (if the extension method doesn't check for null
and throws an exception by itself). You're right that calling non-virtual instance method on null
could work, if that method doesn't access any instance fields of the class (directly or indirectly).
But the language designers felt this would be confusing, so they make sure that the object is not null
by using the callvirt
IL instruction.
With extension methods, this is not as confusing (nobody expects this
to be null
, but an argument declared this IEnumerable<TSource> source
should be checked). And you can call extension method as normal static method, so it should check for null
anyway. Also, both ways of calling the function should probably behave exactly the same.
The instance methods must throw the NullReferenceException
when the object is null, because they inherently guarantee that the object is available when that method is executed. Think of the instance methods as an action that the object instance performs and when the object itself is not existent, then the action could not even be invoked. The extension methods are just syntactic sugar and the compiler immediately translates them as you mentioned above AExt.f(a)
. This is just a convenience and serves as an eye candy to help read the code better.
For the cases where you would want to call a method regardless of whether the instance is available or not, the language provides static methods as the feature. As you can tell, the extension methods are static methods.
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