You have two good and correct answers here, but I understand that answers which simply quote the specification are not always that illuminating. Let me add some additional details.
You probably have a mental model of overload resolution that goes like this:
- Put all the possible methods in a big bucket -- extension methods, static methods, instance methods, etc.
- If there are methods that would be an error to use, eliminate them from the bucket.
- Of the remaining methods, choose the unique one that has the best match of argument expressions to parameter types.
Though this is many people's mental model of overload resolution, regrettably it is subtly wrong.
The real model -- and I will ignore generic type inference issues here -- is as follows:
- Put all the instance and static methods in a bucket. Virtual overrides are not counted as instance methods.
- Eliminate the methods that are inapplicable because the arguments do not match the parameters.
At this point we either have methods in the bucket or we do not. If we have any methods in the bucket at all then extension methods are not checked. This is the important bit right here. The model is not "if normal overload resolution produced an error then we check extension methods". The model is "if normal overload resolution produced no applicable methods whatsoever then we check extension methods".
If there are methods in the bucket then there is some more elimination of base class methods, and finally the best method is chosen based on how well the arguments match the parameters.
If this happens to pick a static method then C# will assume that you meant to use the type name and used an instance by mistake, not that you wish to search for an extension method. Overload resolution has already determined that there is an instance or static method whose parameters match the arguments you gave, and it is going to either pick one of them or give an error; it's not going to say "oh, you probably meant to call this wacky extension method that just happens to be in scope".
I understand that this is vexing from your perspective. You clearly wish the model to be "if overload resolution produces an error, fall back to extension methods". In your example that would be useful, but this behaviour produces bad outcomes in other scenarios. For example, suppose you have something like
mystring.Join(foo, bar);
The error given here is that it should be string.Join
. It would be bizarre if the C# compiler said "oh, string.Join
is static. The user probably meant to use the extension method that does joins on sequences of characters, let me try that..." and then you got an error message saying that the sequence join operator -- which has nothing whatsoever to do with your code here -- doesn't have the right arguments.
Or worse, if by some miracle you did give it arguments that worked but intended the static method to be called, then your code would be broken in a very bizarre and hard-to-debug way.
Extension methods were added very late in the game and the rules for looking them up make them deliberately prefer giving errors to magically working. This is a safety system to ensure that extension methods are not bound by accident.