这个问题再一次让我感到震惊。有人可以提供技术解释,说明为什么以下代码不会产生任何警告或错误。你必须问自己的问题(当然)你感到幸运吗?
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));
}
}
答案 0 :(得分:9)
在第一种情况下,它将调用string
重载。 null
匹配object
和string
,但字符串是更具体/派生的类型。因此,它选择string
。
请查看Eric Lippert的帖子How does the method overload resolution system decide which method to call when a null value is passed?,了解有关此部分重载解析的更长解释。
现在我们必须确定最适合的候选人。最佳性规则很复杂,但简短版本是更具体,优于不太具体。
在第二种情况下,它会选择第一个重载,因为文字7
是int
。如果您使用了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#团队不同意,或者他们根本没有时间添加启发式。