Overriding Extension Methods

前端 未结 9 1248
伪装坚强ぢ
伪装坚强ぢ 2020-12-03 13:57

I\'ve been thinking about using extension methods as a replacement for an abstract base class. The extension methods can provide default functionality, and can be \'overridd

相关标签:
9条回答
  • 2020-12-03 14:20

    Adding a link to another SO question that has an alternate answer than the "You can't". More 'you can't....unless'.

    How to override an existing extension method

    0 讨论(0)
  • 2020-12-03 14:22

    All answers here stated "you can't", which is true as far as it goes. Most added "and you shouldn't". I would like to make the case that you should be able to - small comfort as this may be.

    Take a painful real world example: if you are unfortunate enough to be using the new MVC framework, and your view code is using some HtmlHelper extension method all over the place, and you want to override its default behavior... what then?

    You are SOL, that's what. Even if you did the "OOP thing" - derive from HtmlHelper, change your base view class to replace the 'Html' object instance with an instance of your DerivedHtmlHelper, and define an explicit 'Foo' method in it - even if you did all that, calling 'Html.Foo' will still invoke the original extension method and not method.

    This is surprising! After all, extension methods are only expected to be applied if the object does not already have a method! What's going on here?

    Well, this because extension methods are a static feature. That is, when seeing 'Html.Foo', the compiler looks at the static type of 'Html'. If it has a 'Foo' method, it is called as usual. Otherwise, if there is 'SomeClass' providing a 'Foo' extension method, it converts the expression to 'SomeClass.Foo(Html)'.

    What you would expect is that the compiler would consider the dynamic type of the object. That is, that the generated (pseudo-)code would read 'Html.HasMethod("Foo") ? Html.Foo() : SomeClass.Foo(Html)'.

    This of course would incur the cost of using reflection in each extension method call. So, you would expect that you could write something like 'static void Foo(virtual this HtmlHelper html)' to explicitly request the compiler to insert the run-time check. Call this a "virtual extension method".

    However, in their limited budget and infinite wisdom, the C# language designers went with only the more efficient, more restricted alternative. Which leaves me still SOL when I need to override the default behavior of HtmlHelper :-(

    0 讨论(0)
  • 2020-12-03 14:23

    There's every reason you shouldn't do it. The first of which is, you can't guarantee how your extensions will be called:

    MyExtensions.AMethod(myObj)
    

    or

    myObj.AMethod()
    

    The second is merely syntactic sugar for the first.

    What you suggest goes against the spirit of the language feature. Extension methods are decidedly not object-oriented. Yet you are trying to achieve an object-oriented technique. Don't use extension methods for that.

    0 讨论(0)
提交回复
热议问题