我有两个重载的泛型方法:
T Foo<T>(T t) { Console.WriteLine("T"); return t; }
T Foo<T>(int i) { Console.WriteLine("int"); return default(T); }
当我尝试在计算机上按如下方式呼叫Foo
时:
Foo(5);
我没有编译器错误或警告,并且调用带有泛型参数的 first 方法(即输出为T
)。 在所有C#版本和所有平台上都会出现这种情况吗?在那种情况下,为什么?
另一方面,如果我在通用调用中明确指定类型:
Foo<int>(5);
调用带有int
参数的第二个方法,即输出现在为int
。的为什么吗
我在两个方法重载中使用不同的参数名称,因此以下调用的输出符合预期:
Foo<int>(t: 5); // output 'T'
Foo<int>(i: 5); // output 'int'
如果我调用第一种方法,我甚至可以省略类型规范:
Foo(t: 5); // output 'T'
但是如果我尝试编译它:
Foo(i: 5);
我收到错误无法从用法中推断出方法'Foo(int)'的类型参数。尝试明确指定类型参数。 为什么编译器不能处理此调用?
注意这些测试是在Windows 8 x64系统上使用 LinqPad 执行的(如果与结果相关...)
答案 0 :(得分: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更具体:
- 类型参数的特定性低于非类型参数。
(强调补充)