Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic method overloading and precedence

I have two overloaded generic methods:

T Foo<T>(T t) { Console.WriteLine("T"); return t; }

T Foo<T>(int i) { Console.WriteLine("int"); return default(T); }

When I try to call Foo as follows on my computer:

Foo(5);

I get no compiler errors or warnings, and the first method with the generic argument is called (i.e. the output is T). Will this be the case in all C# incarnations and on all platforms? In that case, why?

On the other hand, if I explicitly specify the type in the generic call:

Foo<int>(5);

the second method with the int argument is called, i.e. the output is now int. Why?

I am using different argument names in my two method overloads, so the output from the following calls are as expected:

Foo<int>(t: 5);       // output 'T'
Foo<int>(i: 5);       // output 'int'

If I am calling the first method, I can even leave out the type specification:

Foo(t: 5);            // output 'T'

But if I try to compile this:

Foo(i: 5);

I get an error The type arguments for method 'Foo(int)' cannot be inferred from the usage. Try specifying the type arguments explicitly. Why cannot the compiler deal with this call?

Note These tests have been performed with LinqPad on a Windows 8 x64 system (in case that is relevant to the results...)

like image 250
Anders Gustafsson Avatar asked May 21 '13 14:05

Anders Gustafsson


People also ask

How can generic method be overloaded?

A generic method can also be overloaded by nongeneric methods. When the compiler encounters a method call, it searches for the method declaration that best matches the method name and the argument types specified in the call—an error occurs if two or more overloaded methods both could be considered best ...

What will happen if overloaded functions have same arguments but different return type?

Overloading with same arguments and different return type − The return type doesn't matter. If they don't have different parameters, they both are still considered as same method and a compile time error will be generated.

Can overloading happen in different classes?

Overloading can happen in same class as well as parent-child class relationship whereas overriding happens only in an inheritance relationship.

How can generic methods be overloaded develop a code with example?

A generic method can also be overloaded by non-generic methods that have the same method name and number of parameters. When the compiler encounters a method call, it searches for the method declaration that most precisely matches the method name and the argument types specified in the call.


1 Answers

Last question

Since you specified (by parameter name) that it should call the overload that takes an int parameter, the compiler has no idea what to pass for T.

First question

Because of this, Foo(5) only matches one overload (Foo<T>()).
Therefore, it must only call Foo<T>().

Second question

When you explicitly specify a type argument (<int>), both overloads are applicable.
In that case, Foo(int) is better, since its parameter is not of generic type.

As per the C# spec §7.5.3.2:

  • Otherwise, if MP has more specific parameter types than MQ, then MP is better than MQ. Let {R1, R2, …, RN} and {S1, S2, …, SN} represent the uninstantiated and unexpanded parameter types of MP and MQ. MP’s parameter types are more specific than MQ’s if, for each parameter, RX is not less specific than SX, and, for at least one parameter, RX is more specific than SX:
    • A type parameter is less specific than a non-type parameter.

(emphasis added)

like image 143
SLaks Avatar answered Sep 24 '22 03:09

SLaks