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...)
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 ...
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.
Overloading can happen in same class as well as parent-child class relationship whereas overriding happens only in an inheritance relationship.
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.
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
.
Because of this, Foo(5)
only matches one overload (Foo<T>()
).
Therefore, it must only call Foo<T>()
.
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With