至于仿制药和IEnumerable方法重载解析方法、IEnumerable

2023-09-03 00:06:52 作者:本宫不退位,尔等终为妃

我注意到这个有一天,说你有两个重载的方法:

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"); 
}

这code:

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

为什么人[] 名单,其中,人物&GT; 更符合 T 比他们到的IEnumerable&LT; T&GT; 在这种情况下

Why are Person[] and List<Person> better matched to T than they are to IEnumerable<T> in these cases?

谢谢

更新: 另外,如果您有其他重载

UPDATE: Also, if you have another overload

public void Print<T>(List<T> items) {
    Console.WriteLine("List T");
}

打印(persons.ToList()); 将实际打印列表牛逼而不是单牛逼

Print(persons.ToList()); will actually print List T instead of Single T.

推荐答案

你的问题的第一部分(不带表专用过载)很容易。让我们考虑的阵列呼叫,因为它的工作原理是相同的两个呼叫:

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:

首先,类型推断产生的通话两种可能的通用实现:打印&LT;人[]&GT;(人[]项目)打印和LT ;人&GT;(IEnumerable的&LT;人&GT;项目)

First, type inference produces two possible generic implementations of the call: Print<Person[]>(Person[] items) and Print<Person>(IEnumerable<Person> items).

然后超载分辨率踢和第一个获胜,因为第二要求的隐式转换,其中,第一个不(参见C#spec的§7.4​​.2.3)。同样的机制在清单变。

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.

通过增加过载,第三个可能的过载与List调用生成:打印&LT;人&GT;(名单&LT;人&GT;项目)。该参数是一样的打印&LT;列表&LT;人&GT;&GT;(名单&LT;人&GT;项目)但同样,第7.4.3.2提供的语言分辨率

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.

因此​​,打印&LT;人&GT; 过载比打印和LT更具体;列表&LT;人&GT;&GT; 超载和List版本战胜了IEnumerable,因为它不需要隐式转换。

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.