public enum EnumTest
{
EnumEntry
}
public class TestClass
{
public string FunctionMember(string s, EnumTest t = EnumTest.EnumEntry)
{
return "Normal";
}
public string FunctionMember<T>(T t)
{
return "Generic";
}
}
class Program
{
static void Main(string[] args)
{
TestClass t = new TestClass();
Console.WriteLine(t.FunctionMember("a"));
}
}
This prints "Generic". Removing , EnumTest t = EnumTest.EnumEntry
makes it print "Normal".
And yet the standard appears to be pretty clear, from 14.4.2.2 Better function member the first discriminator to be applied is:
Am I missing something or compiler bug?
Yes, There are two level where you can apply generic type . You can apply generic type on Method level as well as Class level (both are optional). As above example you applied generic type at method level so, you must apply generic on method return type and method name as well. You need to change a bit of code.
Generic is a class which allows the user to define classes and methods with the placeholder. Generics were added to version 2.0 of the C# language. The basic idea behind using Generic is to allow type (Integer, String, … etc and user-defined types) to be a parameter to methods, classes, and interfaces.
Generics are classes, structures, interfaces, and methods that have placeholders (type parameters) for one or more of the types that they store or use.
You are missing something. And that is the following:
You call the method with one parameter. There is only one method that has one parameter, the generic one. So that's the one that's chosen.
Only if it didn't find a matching method it would look at other methods with optional parameters.
References:
C# 4.0 Specification, last paragraph in 21.4:
As a tie breaker rule, a function member for which all arguments where explicitly given is better than one for which default values were supplied in lieu of explicit arguments.
MSDN, heading "Overload resolution", last bullet point:
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
The C# Language Specification, Chapter "7.5.3.2 Better function member":
Parameter lists for each of the candidate function members are constructed in the following way:
- The expanded form is used if the function member was applicable only in the expanded form.
- Optional parameters with no corresponding arguments are removed from the parameter list
It continues like this:
Given an argument list A with a set of argument expressions { E1, E2, ..., EN } and two applicable function members MP and MQ with parameter types { P1, P2, ..., PN } and { Q1, Q2, ..., QN } [...]
At this point the method with the optional parameter is already out of the game. N
is 1, but that method has two parameters.
The docs say:
If two candidates are judged to be equally good, preference goes to a candidate that does not have optional parameters for which arguments were omitted in the call. This is a consequence of a general preference in overload resolution for candidates that have fewer parameters.
In other words, the method without any optional arguments will be preferred.
With default values for method parameters the overload resolution got extended.
Conceptually the method overload resolution from pre v4 will be run. If that finds a match that match will be used. (Conceptually because this is not a description of how it works but how you can think of it)
In your case it finds exactly one match being your generic method
If it does not find a match it will look for methods that has a partial match and where the match can be completed with default values. In your case your none generice method would be found in this run however the resolution never comes this far due to already having found a match.
When removing the second paramter you end up in a situation where there's a generic and a non generic match. And the rule you qoute kicks in picking the non-generic.
All in all a good rule of thumb is that the most specific available method will be chosen.
A non-generic method that matches is more specific than a generic because the type can't vary. A method with default parameters is less specific than one where the argument count matches the parameter count (the numbers are an exact match) if two methods are available but one takes an argument of IFoo and the other takes a Foo (implemeting IFoo) then the latter will be chosen when passing a Foo object as argument because it's an exact match Ie. more specific
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