模糊方法重载

时间:2012-01-26 11:17:49

标签: c# overloading

这个问题再一次让我感到震惊。有人可以提供技术解释,说明为什么以下代码不会产生任何警告或错误。你必须问自己的问题(当然)你感到幸运吗?

class Program
{
    static string Feeling(object o) { return "Lucky"; }
    static string Feeling(string s) { return "Unlucky"; }

    static void Main(string[] args)
    {
        Console.WriteLine("I feel " + Feeling(null));
    }
}

如果您知道在没有运行代码的情况下将使用调用哪种方法,则会获得奖励积分。 只是为了添加侮辱,它不仅仅发生在null参数上:

class Program
{
    static string Feeling(int i) { return "Lucky"; }
    static string Feeling(uint i) { return "Unlucky"; }

    static void Main(string[] args)
    {
        Console.WriteLine("I feel " + Feeling(7));
    }
}

1 个答案:

答案 0 :(得分:9)

第一个例子:null参数

在第一种情况下,它将调用string重载。 null匹配objectstring,但字符串是更具体/派生的类型。因此,它选择string

请查看Eric Lippert的帖子How does the method overload resolution system decide which method to call when a null value is passed?,了解有关此部分重载解析的更长解释。

  

现在我们必须确定最适合的候选人。最佳性规则很复杂,但简短版本是更具体,优于不太具体。

第二个例子:整数文字

在第二种情况下,它会选择第一个重载,因为文字7int。如果您使用了7u,那么它将是uint,因此第二次重载将是首选。

整数文字具有定义良好的类型(即使它们允许比正常的整数值更多的隐式转换)。您可以将u等后缀用于无符号,或l长期用于影响该类型。或者你可以添加一个显式的演员。

虽然int通常无法隐式转换为uint,但这是一个整数常量,其有效范围为uint ,并且C#编译器有一个额外的规则允许整数常量之间的隐式转换,前提是常量符合目标的范围。

Eric再次解释了详细信息:Why does this implicit conversion from int to uint work?

  

如果constant-expression的值在目标类型的范围内,则int类型的常量表达式可以转换为sbyte,byte,short,ushort,uint或ulong类型。如果常量表达式的值不是负数,则long类型的常量表达式可以转换为ulong类型。


在两个示例中,就C#编译器而言,一个重载显然是最好的,因此您不会出现模糊的重载错误。

我个人认为第一个例子应该发出警告,但是C#团队不同意,或者他们根本没有时间添加启发式。