关于泛型和I可数值的方法过载解析

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (12)

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

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节)。相同的机制也适用于列表变体。

通过添加的重载,使用列表调用生成第三个可能的重载:Print<Person>(List<Person> items).参数与Print<List<Person>>(List<Person> items)但是,第7.4.3.2节再次提供了该决议所用的语言

递归地说,如果至少有一个类型参数更具体,而在另一个类型参数中没有类型参数比对应类型参数更具体,则构造类型比另一个构造类型更具体(具有相同数量的类型参数)。

所以Print<Person>重载比Print<List<Person>>重载和列表版本赢得了IEnDigable的支持,因为它不需要隐式转换。

用户回答回答于

Because the methods generated from the generics 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>)...

扫码关注云+社区