以下代码在编译时抛出“不明确的调用匹配”:
class ABC{}
class DEF{}
class Program
{
static void Main(string[] args)
{
Debug.WriteLine(func(null));
}
static string func(ABC abc)
{
return "";
}
static string func(DEF def)
{
return "";
}
}
但是下面的代码编译并运行良好:
static void Main(string[] args)
{
Debug.WriteLine(func(null));
}
static string func(int? abc)
{
return "function a";
}
static string func(float? def)
{
return "function b";
}
对外输出
function a
C#如何知道在第二个例子中选择哪个函数?
答案 0 :(得分:12)
当编译器对这样的函数调用执行重载解析时,它会在候选项中选择更好的函数成员(如果存在)。 更好的函数成员的定义包括C#语言规范§7.5.3.2中的这一段:
7.5.3.2更好的职能成员
[...]
给定参数列表A,其中包含一组参数表达式{E1,E2, ...,EN}和两个适用的函数成员MP和MQ带参数 类型{P1,P2,...,PN}和{Q1,Q2,...,QN},MP定义为 如果
,则比MQ更好的函数成员
- 对于每个参数,从EX到QX的隐式转换是 不比从EX到PX的隐式转换和
更好- 对于至少一个参数,从EX到PX的转换是 比从EX到QX的转换更好。
[...]
在这种情况下,MP
是第一种方法(P1
为int?
)而MQ
是第二种方法(Q1
为float?
})。因此,如果我们能够证明从null
到int?
的转换更好而不是转换为float?
,则很容易解释这种行为。
这取决于§7.5.3.5中的规则:
7.5.3.5更好的转换目标
鉴于T1和T2两种不同的类型,T1是更好的转换目标 如果至少满足下列条件之一,则为T2:
- 存在从T1到T2的隐式转换,并且不存在从T2到T1的隐式转换
由于存在从int
到float
的隐式转换,但从float
到int
的转换不存在(reference),int
是在两种类型之间进行选择时,更好的转换目标。
在您的示例中,我们正在处理这些类型的可空版本,但由于
,同样的逻辑适用6.1.4隐式可空转换
对非可空值进行操作的预定义隐式转换 类型也可以与这些类型的可空形式一起使用。