5

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

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# 如何知道在第二个示例中选择哪个函数?

4

1 回答 1

12

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

7.5.3.2 更好的函数成员

[...]

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

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

[...]

在这种情况下,MP是第一种方法(P1being int?)并且MQ是第二种方法(Q1being float?)。因此,如果我们可以证明从nulltoint?的转换优于float?to 的转换,则该行为很容易解释。

这是由 §7.5.3.5 中的规则确定的:

7.5.3.5 更好的转化目标

给定两种不同类型的 T1 和 T2,如果以下至少一项成立,则 T1 是比 T2 更好的转化目标:

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

由于存在从 to 的隐式转换但不存在从to的隐式转换(参考int因此在两种类型之间进行选择时是更好的转换目标。floatfloatintint

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

6.1.4 隐式可空转换

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

于 2013-05-15T23:08:43.210 回答