开发者

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

开发者 https://www.devze.com 2023-04-02 01:04 出处:网络
Consider this code: A a = null; a.f(); //Will it throw NullReferenceException? Will the above throw NullReferenceException?

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

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号