views:

130

answers:

2

I wrote an extension method for String to get a char argument, string.Remove(char). But when I used this, it instead called the default string.Remove(int) method.

Shouldn't the presence of an actual method have higher priority than an implicit conversion?

+2  A: 

Instance methods have priority over extension methods. Your observation is proof of the same.

When resolving which method to call, it will always pick a matching instance method over an extension method... which is intuitive in a way.

Paraphrased from C# in depth,

When the compiler sees that you're trying to call a method which looks like an instance method but is unable to find one, it then looks for extension methods (that are visible based on your using directives). In case of multiple candidates as the target extension method, the one with "better conversion" similar to overloading (e.g. if IChild and IBase both have a similar extension method defined.. IChild.ExtensionMethod is chosen)

Also a hidden code-breaker could be lets say TypeA didn't have SecretMethod as an instance method in Libv1.0. So you write an extension method SecretMethod. If the author introduces an instance method of the same name and signature in v2.0 (sans the this param), and you recompile your source with the latest-n-greatest Libv2.0, all existing calls to the extension method would silently now be routed to the new instance method.

Gishu
Yeah but at least there is no direct method, just one that requires an implicit cast. So I expected it would look for a direct method.
Joan Venge
"all existing calls to the extension method would silently now be routed to the new instance method." - Note this only counts when recompiling. An extension call is just plainly translated into an static method call.
Dykam
The compiler will try its best to satisfy the method resolution request with an instance method - using implicit conversions if necessary. It looks at extension methods only if it couldn't. Also trying implicit casts to find an instance method is std. behavior. e.g MyFunc('A') will resolve to static void MyFunc(int a) with a = 65. You can avoid all this by just defining your extension method to a name that is not taken - but you can never be sure, see last para.
Gishu
@Dykam - point. I should explicitly state that. Updated and Thanks
Gishu
+1  A: 

This behavior is correct. The reason is that introducing an extension method should not change the way existing code executes. Code should behave exactly the same with or without this "superfluous" extension method. It may seem counter-intuitive in certain cases (like yours), but happens for a reason.

Snarfblam