模糊调用匹配混乱

时间:2013-05-15 22:54:55

标签: 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 "";
    }
}

但是下面的代码编译并运行良好:

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

1 个答案:

答案 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是第一种方法(P1int?)而MQ是第二种方法(Q1float? })。因此,如果我们能够证明从nullint?的转换更好而不是转换为float?,则很容易解释这种行为。

这取决于§7.5.3.5中的规则:

  

7.5.3.5更好的转换目标

     

鉴于T1和T2两种不同的类型,T1是更好的转换目标   如果至少满足下列条件之一,则为T2:

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

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

在您的示例中,我们正在处理这些类型的可空版本,但由于

,同样的逻辑适用
  

6.1.4隐式可空转换

     

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