Back to the basics: Overload resolution in C#

Akos Nagy
Oct 21, 2017

During one of my courses, and interesting question came up. Let's say you have a class definition like this:

public class Test<T>
    public void Method(T parameter) {}
    public void Method(int parameter) {}
// ...
// Test<int> object = new Test<int>();
// object.Method(7);

So, as you can probably guess, the question was about which overload would be called. And, I have to admit, I didn't know the answer, so we tried it together, and the 'second one' was called.

Of course the real question is not which one, but why that one :)
So I dig into the C# language specs to find out why. The overload resolution process is described in the Expressions section. First, to find the best overload, the set of all possible overloads must be found. These are called applicable function members. There is a whole bunch of rules to find the overloads. As you might guess, the two methods are valid candidates for the method call.

After determining the applicable members, the best one has to be found. Which is the best one? The one compared to which there are no better ones. What makes an overload better than the other? Betterness is based on arguments matching the declared parameter types of methods. If there is a tie (like in this case), there are a number of tie-breaking criteria to determine which is the better (it's somewhere on page 128).

1; The first one says that a non-generic method is better than a generic one. Does this apply? No, it doesn't. The class is generic, but the first method is not. Something can only be generic if there is a generic type parameter declared in its declaration (again, there is a line in the specs about this somewhere).
2; The second and the third rules deal with params arrays, which we don't have.
3; The fourth says, that the best is the one which has at least one more specific parameter (with the other ones being not less specific). Then the rule goes on to list what 'more specific' means. The first one says that a type parameter is less specific than a non-type parameter. Now the second method has a non-type parameter, but what about a first one? Is 'T' a type parameter, even though the method is not generic?

Well, the answer is yes. Again, the specs gives some details about this (the actual sentence falls right onto the page break between line 40 and 41) and states that the scope of a type parameter declared in the class declaration includes the class body, hence the method declarations. So yes, 'T' is a type parameter, just not of the method, but of the enclosing class. And so, the overload with 'T' is less specific than the overload with int. Q.E.D.

Akos Nagy
Posted in C# Teaching