前几天我注意到这一点,假设你有两个重载的方法:
public void Print<T>(IEnumerable<T> items) {
Console.WriteLine("IEnumerable T");
}
public void Print<T>(T item) {
Console.WriteLine("Single T");
}
这段代码:
public void TestMethod() {
var persons = new[] {
new Person { Name = "Yan", Age = 28 },
new Person { Name = "Yinan", Age = 28 }
};
Print(persons);
Print(persons.ToList());
}
打印:
Single T
Single T
为什么在这些情况下,Person[]
和List<Person>
与T
的匹配度要高于与IEnumerable<T>
的匹配度?
谢谢,
更新:也是,如果你有另一个重载
public void Print<T>(List<T> items) {
Console.WriteLine("List T");
}
Print(persons.ToList());
实际上将打印List T
而不是Single T
。
发布于 2011-02-06 07:14:37
问题的第一部分(没有特定于列表的重载)很简单。让我们考虑一下Array调用,因为它对于两个调用都是一样的:
首先,类型推断生成该调用的两种可能的泛型实现:Print<Person[]>(Person[] items)
和Print<Person>(IEnumerable<Person> items)
。
然后重载解析开始生效,第一个重载解析获胜,因为第二个需要隐式转换,而第一个不需要(参见C#规范的§7.4.2.3 )。同样的机制也适用于列表变体。
使用添加的重载,使用列表调用生成第三个可能的重载:Print<Person>(List<Person> items)
。该参数与Print<List<Person>>(List<Person> items)
相同,但7.4.3.2节提供了包含该语言的解决方案
递归地,如果至少有一个类型参数比另一个类型参数更具体,并且没有类型参数比另一个类型参数更具体,则构造的类型比另一个构造的类型(具有相同数量的类型参数)更具体。
因此,Print<Person>
重载比Print<List<Person>>
重载更具体,列表版本胜过IEnumerable,因为它不需要隐式转换。
发布于 2011-02-06 06:13:12
因为从泛型Print(Person[] item)
和Print(List<Person> item)
生成的方法比IEnumerable<T>
更匹配。
编译器根据您的类型参数生成这些方法,因此通用模板Print<T>(T item)
将编译为Print(Person[] item)
和Print(List<Person> item)
(好吧,无论编译时表示List<Person>
的是什么类型)。因此,编译器会将方法调用解析为接受直接类型的特定方法,而不是Print(IEnumerable<Peson>)
的实现。
https://stackoverflow.com/questions/4910018
复制相似问题