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.
- If it’s a member method, then yes, it will throw exception.
- If it’s an extension method, then no, it will not throw any extension.
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
nulland throws an exception by itself). You’re right that calling non-virtual instance method onnullcould 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
nullby using thecallvirtIL instruction.With extension methods, this is not as confusing (nobody expects
thisto benull, but an argument declaredthis IEnumerable<TSource> sourceshould be checked). And you can call extension method as normal static method, so it should check fornullanyway. Also, both ways of calling the function should probably behave exactly the same.