c# - 关于泛型和 IEnumerable 的方法重载解析

标签 c# .net overloading overload-resolution

前几天我注意到了这一点,假设你有两个重载方法:

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 .

最佳答案

问题的第一部分(没有特定于列表的重载)很简单。让我们考虑 Array 调用,因为它对两个调用的作用相同:

首先,类型推断产生调用的两个可能的通用实现:Print<Person[]>(Person[] items)Print<Person>(IEnumerable<Person> items) .

然后重载决议开始,第一个获胜,因为第二个需要隐式转换,而第一个不需要(参见 C# 规范的 §7.4.2.3)。相同的机制适用于 List 变体。

通过添加重载,List 调用会生成第三种可能的重载:Print<Person>(List<Person> items) .参数与 Print<List<Person>>(List<Person> items) 相同但同样,第 7.4.3.2 节提供了语言的解决方案

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.

所以 Print<Person>重载比 Print<List<Person>> 更具体重载并且 List 版本胜过 IEnumerable,因为它不需要隐式转换。

关于c# - 关于泛型和 IEnumerable 的方法重载解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4910018/

相关文章:

c# - 在 ASP.Net 应用程序中安全地存储(加密)数据

c# - 获取我的应用程序的当前点网络版本

C# Async/Await 从不在 MVC4 中响应

c# windows 窗体在 windows cmd 上显示输出代码

c++ - 错误 : "2 overloads have similar conversions"

C++ 库的 C# 绑定(bind)

c# - 使用具有流畅验证的自定义验证响应

c# - 在 Vista 中获取可移植设备的路径

java - 将通用 Java 输入限制为两种类型之一

C# - 方法无重载(采用 0 个参数)