Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Extension Method and Member Method : why each is implemented differently by compilers (internally)?

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).

like image 453
Nawaz Avatar asked Oct 24 '22 01:10

Nawaz


2 Answers

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.

like image 183
svick Avatar answered Oct 30 '22 23:10

svick


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.

like image 32
Charles Prakash Dasari Avatar answered Oct 31 '22 01:10

Charles Prakash Dasari