模糊调用匹配混乱

Isa*_*aac 5 c# null nullable overload-resolution

以下代码在编译时抛出"不明确的调用匹配":

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 "";
    }
}
Run Code Online (Sandbox Code Playgroud)

但是下面的代码编译并运行正常:

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";
}
Run Code Online (Sandbox Code Playgroud)

输出

function a
Run Code Online (Sandbox Code Playgroud)

C#如何知道在第二个例子中选择哪个函数?

Jon*_*Jon 12

当编译器对这样的函数调用执行重载解析时,它会在候选中选择更好的函数成员(如果存在).更好的函数成员的定义包括C#语言规范的第7.5.3.2节中的这一段:

7.5.3.2更好的功能成员

[...]

给定一个参数列表A,其中包含一组参数表达式{E1,E2,...,EN}和两个适用的函数成员MP和MQ,参数类型为{P1,P2,...,PN}和{Q1,Q2, ...,QN},MP被定义为比MQ更好的函数成员if

  • 对于每个参数,从EX到QX的隐式转换并不比从EX到PX的隐式转换更好
  • 对于至少一个参数,从EX到PX的转换优于从EX到QX的转换.

[...]

在这种情况下,MP是第一种方法(P1存在int?),MQ是第二种方法(Q1存在float?).所以,行为很容易解释的.如果我们能证明,从转换nullint?更好地比转换float?.

这由§7.5.3.5中的规则决定:

7.5.3.5更好的转换目标

给定两种不同类型T1和T2,如果至少有以下一种情况,则T1是比T2更好的转换目标:

  • 存在从T1到T2的隐式转换,并且不存在从T2到T1的隐式转换

由于从隐式转换intfloat存在,但一个从floatint不(参考),int更好的转换目标的两种类型之间进行选择时.

在您的示例中,我们正在处理这些类型的可空版本,但同样的逻辑适用于

6.1.4隐式可空转换

对非可空值类型进行操作的预定义隐式转换也可以与这些类型的可空形式一起使用.