I want to replace extension methods included in the .NET or ASP MVC framework by my own methods.
Example
public static string TextBox(this HtmlHelper htmlHelper, string name) { ... }
Is it possible? I can't use the override or new keyword.
Extension methods cannot be overridden the way classes and instance methods are. They are overridden by a slight trick in how the compiler selects which extension method to use by using "closeness" of the method to the caller via namespaces.
An extension method must be defined in a top-level static class. An extension method with the same name and signature as an instance method will not be called. Extension methods cannot be used to override existing methods. The concept of extension methods cannot be applied to fields, properties or events.
It is not possible to override functionality (like properties or methods) in extensions as documented in Apple's Swift Guide. Extensions can add new functionality to a type, but they cannot override existing functionality. The compiler is allowing you to override in the extension for compatibility with Objective-C.
Ambiguity can be resolved if concurrent namespaces which have extension methods with same name, are included at different levels (most inner included namespace will have priority).
UPDATE: This question was the subject of my blog in December of 2013. Thanks for the great question!
You can do this, in a sense. But I should start by talking briefly about the basic design principle of overload resolution in C#. All overload resolution is, of course, about taking a set of methods with the same name and choosing from that set the unique best member to call.
There are many factors involved in determining which is the "best" method; different languages use a different "mixture" of factors to figure this out. C# in particular heavily weights "closeness" of a given method to the call site. If given the choice between an applicable method in a base class or a new applicable method in a derived class, C# takes the one in the derived class because it is closer, even if the one in the base class is in every other way a better match.
And so we run down the list. Derived classes are closer than base classes. Inner classes are closer than outer classes. Methods in the class hierarchy are closer than extension methods.
And now we come to your question. The closeness of an extension method depends on (1) how many namespaces "out" did we have to go? and (2) did we find the extension method via using
or was it right there in the namespace? Therefore you can influence overload resolution by changing in what namespace your static extension class appears, to put it in a closer namespace to the call site. Or, you can change your using
declarations, to put the using
of the namespace that contains the desired static class closer than the other.
For example, if you have
namespace FrobCo.Blorble { using BazCo.TheirExtensionNamespace; using FrobCo.MyExtensionNamespace; ... some extension method call }
then it is ambiguous which is closer. If you want to prioritize yours over theirs, you could choose to do this:
namespace FrobCo { using BazCo.TheirExtensionNamespace; namespace Blorble { using FrobCo.MyExtensionNamespace; ... some extension method call }
And now when overload resolution goes to resolve the extension method call, classes in Blorple
get first go, then classes in FrobCo.MyExtensionNamespace
, then classes in FrobCo
, and then classes in BazCo.TheirExtensionNamespace
.
Is that clear?
Extension methods cannot be overridden since they are not instance methods and they are not virtual.
The compiler will complain if you import both extension method classes via namespace as it will not know which method to call:
The call is ambiguous between the following methods or properties: ...
The only way around this is to call your extension method using normal static method syntax. So instead of this:
a.Foo();
you would have to do this:
YourExtensionMethodClass.Foo(a);
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