Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic Method Resolution

Consider the following code:

public class Tests
{
    public void Test()
    {
        Assert.AreEqual("Int", DoSomething(1));
    }

    public static string DoSomething<T>(T value)
    {
        return "Generic";
    }

    public static string DoSomething(int value)
    {
        return "Int";
    }
}

As expected, the non-generic DoSomething method will be invoked. Now consider the following modification:

public class Tests
{
    public void Test()
    {
        Assert.AreEqual("Int", DoSomething(1));
    }

    public static string DoSomething<T>(T value)
    {
        return "Generic";
    }

    public static string DoSomething<T>(int value)
    {
        return "Int";
    }
}

The only thing I've changed is adding the T type parameter to the second overload, thus making it generic. Note that the type parameter is not used.

That modification causes the first DoSomething method to be called. Why? The compiler has all the information it needs in order to choose the second method.

Can you please explain why, or even better, point me to the section of the C# specification that explains this behavior?

like image 236
Moshe Levi Avatar asked Aug 18 '14 16:08

Moshe Levi


1 Answers

In your call, you're not specifying a type argument - so the compiler would have to infer the type of T. It can't do that for your second method, because the type parameter is never mentioned in the declared parameters. Therefore, that overload is not applicable, and is ignored.

If you specify a type argument to the call, e.g. any of

DoSomething<int>(1)
DoSomething<object>(1)
DoSomething<string>(1)

... then in all cases the second overload will be called.

From section 7.6.5.1 of the C# 5 spec, (method invocations) when constructing the set of candidate methods:

  • If F is generic and M has no type argument list, F is a candidate when:
    • Type inference (§7.5.2) succeeds, inferring a list of type arguments for the call, and
    • Once the inferred type arguments are substituted for the corresponding method type parameters, all constructed types in the parameter list of F satisfy their constraints (§4.4.4), and the parameter list of F is applicable with respect to A (§7.5.3.1).

As type inference doesn't succeed, the second method isn't in the candidate set, so by the time we get to real overload resolution, the set just has a single method in (the first one).

like image 95
Jon Skeet Avatar answered Oct 10 '22 04:10

Jon Skeet