关于泛型和 IEnumerable 的方法重载解析
前几天我注意到这一点,假设你有两个重载方法:
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());
}
prints:
Single T
Single T
Why are Person[]
and List
better matches to T
比这些情况下的 IEnumerable
更重要吗?
谢谢,
更新: 另外,如果您有另一个重载
public void Print<T>(List<T> items) {
Console.WriteLine("List T");
}
Print(persons.ToList());
将实际打印 List T
而不是 Single T
。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
你的问题的第一部分(没有特定于列表的重载)很简单。让我们考虑一下 Array 调用,因为它对于两个调用的工作方式相同:
首先,类型推断会生成该调用的两个可能的通用实现:(IEnumerable项目)。
Print(Person[] items)
和 <代码>打印然后重载解析开始,第一个获胜,因为第二个需要隐式转换,而第一个不需要(请参阅 C# 规范的第 7.4.2.3 节)。相同的机制适用于 List 变体。
添加重载后,List 调用会生成第三种可能的重载:
Print(List items)
。该参数与Print
相同,但第 7.4.3.2 节再次提供了语言的解决方案>(List items)
因此,
Print
重载比Print
重载更具体,并且 List 版本胜过 IEnumerable,因为它不需要隐式转换。>
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)
andPrint<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 thePrint<List<Person>>(List<Person> items)
but again, section 7.4.3.2 provides the resolution with the languageSo the
Print<Person>
overload is more specific than thePrint<List<Person>>
overload and the List version wins over the IEnumerable because it requires no implicit conversion.因为从泛型
Print(Person[] item)
和Print(List item)
生成的方法比IEnumerable< 更匹配。 /代码>。
编译器根据您的类型参数生成这些方法,因此通用模板
Print(T item)
将编译为Print(Person[] item)
并且Print(List item)
(好吧,无论什么类型在编译时都代表List
)。因此,编译器会将方法调用解析为接受直接类型的特定方法,而不是Print(IEnumerable)
的实现。Because the methods generated from the generics
Print(Person[] item)
andPrint(List<Person> item)
are a better match thanIEnumerable<T>
.The compiler is generating those methods based on your type arguments, so the generic template
Print<T>(T item)
will get compiled asPrint(Person[] item)
andPrint(List<Person> item)
(well, whatever type represents aList<Person>
at compilation). Because of that, the method call will be resolved by the compiler as the specific method that accepts the direct type, not the implementation ofPrint(IEnumerable<Peson>)
.