通用方法重载和优先级

And*_*son 5 c# generics overload-resolution

我有两个重载的泛型方法:

T Foo<T>(T t) { Console.WriteLine("T"); return t; }

T Foo<T>(int i) { Console.WriteLine("int"); return default(T); }
Run Code Online (Sandbox Code Playgroud)

当我尝试Foo在我的电脑上调用如下:

Foo(5);
Run Code Online (Sandbox Code Playgroud)

我没有编译器错误或警告,并调用带泛型参数的第一个方法(即输出T).在所有C#化身和所有平台上都会出现这种情况吗?在那种情况下,为什么?

另一方面,如果我在泛型调用中明确指定类型:

Foo<int>(5);
Run Code Online (Sandbox Code Playgroud)

调用带参数的第二个方法int,即输出现在int.为什么?

我在两个方法重载中使用不同的参数名称,因此以下调用的输出是预期的:

Foo<int>(t: 5);       // output 'T'
Foo<int>(i: 5);       // output 'int'
Run Code Online (Sandbox Code Playgroud)

如果我调用第一种方法,我甚至可以省略类型规范:

Foo(t: 5);            // output 'T'
Run Code Online (Sandbox Code Playgroud)

但是,如果我尝试编译这个:

Foo(i: 5);
Run Code Online (Sandbox Code Playgroud)

我得到一个错误方法'Foo(int)'的类型参数不能从用法中推断出来.尝试显式指定类型参数. 为什么编译器不能处理这个调用?

注意这些测试是在Windows 8 x64系统上使用LinqPad执行的(如果与结果相关...)

SLa*_*aks 7

最后一个问题

由于您指定(通过参数名称)它应该调用带int参数的重载,因此编译器不知道要传递什么T.

第一个问题

因此,Foo(5) 只匹配一个重载(Foo<T>()).
因此,它必须只能打电话Foo<T>().

第二个问题

显式指定类型参数(<int>)时,两个重载都适用.
在这种情况下,Foo(int)更好,因为它的参数不是泛型类型.

根据C#规范§7.5.3.2:

  • 否则,如果MP具有比MQ更多的特定参数类型,则MP优于MQ.设{R1,R2,...,RN}和{S1,S2,...,SN}表示MP和MQ的未实例化和未展开的参数类型.MP的参数类型比MQ更具体,如果对于每个参数,RX的特定性不低于SX,并且对于至少一个参数,RX比SX更具体:
    • 类型参数不是非类型参数的特定参数.

(重点补充)