通用与非通用过载调用

时间:2012-03-29 09:02:59

标签: c# generics .net-4.0 overloading

当我声明这样的方法时:

void DoWork<T>(T a) { }
void DoWork(int a) { }

用这个称呼它:

int a = 1;
DoWork(a);

它会调用什么DoWork方法?为什么?我似乎无法在任何MSDN文档中找到它。

1 个答案:

答案 0 :(得分:9)

正如Eric Lippert says

  

C#规范说明当你在调用ReallyDoIt<string>(string)ReallyDoIt(string)之间做出选择时 - 也就是说,当选择在两个具有相同签名的方法之间时,但是一个通过泛型替换获得该签名 - 然后我们在“替代”签名上选择“自然”签名。

更新:

我们在C#规范(7.5.3)中有什么:

如果在未指定类型参数的情况下调用泛型方法,则类型推断过程会尝试推断调用的类型参数。通过类型推断,类型参数int由方法的参数确定。类型推断作为方法调用的绑定时处理的一部分发生,并且发生before调用的重载决策步骤。

如果在方法调用中指定了特定方法组,并且未将任何类型参数指定为方法调用的一部分,则会将类型推断应用于方法组中的每个泛型方法。如果类型推断成功,则推断的类型参数用于确定后续重载解析的参数类型。如果重载解析选择泛型方法作为要调用的方法,则推断的类型参数将用作调用的实际类型参数。如果特定方法的类型推断失败,则该方法不参与重载解析。

所以在重载解析之前,我们在方法组中有两个方法。一个DoWork(int)和其他推断的DoWork<int>(int)

我们转到7.5.3.2(更好的功能成员):

如果参数类型序列{P1,P2,...,PN}和{Q1,Q2,...,QN}是等效的(即每个Pi具有到相应Qi的标识转换),则以下打破平局规则按顺序应用,以确定更好的功能成员。 1)如果MP是非泛型方法而MQ是泛型方法,则MP优于MQ。