I noticed this the other day, say you have two overloaded methods:
public void Print<T>(IEnumerable<T> items) {
Console.WriteLine("IEnumerable T");
}
public void Print<T>(T item) {
Console.WriteLine("Single T");
}
This code:
public void TestMethod() {
var persons = new[] {
new Person { Name = "Yan", Age = 28 },
new Person { Name = "Yinan", Age = 28 }
};
Print(persons);
Print(persons.ToList());
}
prints:
Single T
Single T
Why are Person[]
and List<Person>
better matched to T
than they are to IEnumerable<T>
in these cases?
Thanks,
UPDATE: Also, if you have another overload
public void Print<T>(List<T> items) {
Console.WriteLine("List T");
}
Print(persons.ToList());
will actually print List T
instead of Single T
.
The first part of your question (without the List-specific overload) is easy. Let's consider the Array call, because it works the same for both calls:
First, type inference produces two possible generic implementations of the call: Print<Person[]>(Person[] items)
and Print<Person>(IEnumerable<Person> items)
.
Then overload resolution kicks in and the first one wins, because the second requires an implicit conversion, where the first one does not (see §7.4.2.3 of the C# spec). The same mechanism works for the List variant.
With the added overload, a third possible overload is generated with the List call: Print<Person>(List<Person> items)
. The argument is the same as with the Print<List<Person>>(List<Person> items)
but again, section 7.4.3.2 provides the resolution with the language
Recursively, a constructed type is more specific than another constructed type (with the same number of type arguments) if at least one type argument is more specific and no type argument is less specific than the corresponding type argument in the other.
So the Print<Person>
overload is more specific than the Print<List<Person>>
overload and the List version wins over the IEnumerable because it requires no implicit conversion.
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