Why is the second function called here first and not the first. And how does the choice of functions occur in such situations?
class Program {
static void Main(string[] args) {
var a = new A<char>();
Use(a);
}
static void Use(IEnumerable<char> e) {
foreach (var _ in e) ;
Console.WriteLine("Use(IEnumerable<char>)");
}
static void Use<T>(T e) where T : IEnumerable<char> {
foreach (var _ in e) ;
Console.WriteLine("Use<T>(T) where T : IEnumerable<char>");
}
static void Use<T>(A<char> e) {
foreach (var _ in e) ;
Console.WriteLine("Use<T>(A<char>)");
}
}
class A<T> : IEnumerable<T> {
...
}
Basically, the C# compiler follows very complex rules for overloading. See section 12.6.4 of the C# v7 standard for the painstaking details.
In this particular case, the compiler chooses the generic method instead of the non-generic method because it means the parameter is an exact match for the argument, which is deemed to be a "better conversion". It's a little bit like this:
void M(object o) { ... }
void M(string s) { ... }
...
M("test"); // Calls M(string)
The second method is a "better" function here because the conversion from string
to string
is "better" than the conversion from string
to object
.
In your case, it's a conversion from A<char>
to A<char>
, vs a conversion from A<char>
to IEnumerable<char>
.
As for why the second method is called rather than the third method - your third method is generic, but T
can't be inferred via type inference, so it's not an applicable function member. If you change it to be a non-generic method (static void Use(A<char> e)
), then that will be the best function member, because one of the tie-breaking rules is that a non-generic method is "better" than a generic method.