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

发布于 2024-10-15 19:37:58 字数 966 浏览 6 评论 0 原文

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

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身以后 2024-10-22 19:37:58

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

首先,类型推断会生成该调用的两个可能的通用实现:Print(Person[] items) 和 <代码>打印(IEnumerable项目)。

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

添加重载后,List 调用会生成第三种可能的重载:Print(List items)。该参数与 Print>(List items) 相同,但第 7.4.3.2 节再次提供了语言的解决方案

递归地,如果至少一个类型参数更具体,并且没有类型参数比另一个类型参数中的相应类型参数更具体,则构造类型比另一种构造类型(具有相同数量的类型参数)更具体。< /p>

因此,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) 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.

俏︾媚 2024-10-22 19:37:58

因为从泛型 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) and Print(List<Person> item) are a better match than IEnumerable<T>.

The compiler is generating those methods based on your type arguments, so the generic template Print<T>(T item) will get compiled as Print(Person[] item) and Print(List<Person> item) (well, whatever type represents a List<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 of Print(IEnumerable<Peson>).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文