奇怪(可能是错误的)C#编译器行为与方法重载和枚举

今天我发现一个非常奇怪的行为,C#函数重载.当我有一个有2个重载的方法,一个接受Object,另一个接受任何类型的枚举时,就会出现这个问题.当我通过0作为参数时,调用方法的枚举版本.当我使用任何其他整数值时,将调用Object版本.我知道这可以通过使用显式转换来解决,但是我想知道编译器为什么这样做.这是一个错误还是只是一些陌生的语言规则我不知道?

下面的代码解释了问题(使用运行时2.0.50727检查)

感谢您的任何帮助,
Grzegorz Kyc

class Program
{
    enum Bar
    {
        Value1,Value2,Value3
    }

    static void Main(string[] args)
    {
        Foo(0);
        Foo(1);
        Console.ReadLine();
    }

    static void Foo(object a)
    {
        Console.WriteLine("object");
    }

    static void Foo(Bar a)
    {
        Console.WriteLine("enum");
    }
}

解决方法

这可能是你不知道有一个从constant1为0到任何枚举的隐式转换:
Bar x = 0; // Implicit conversion

现在,从0到Bar的转换比从0到对象的转换更具体,这就是为什么使用Foo(Bar)重载.

这是否清楚了一切?

1 Microsoft C#编译器实际上有一个错误,它允许它为任何零常量,而不仅仅是一个整数:

const decimal DecimalZero = 0.0m;

...
Bar x = DecimalZero;

这不太可能会被修复,因为它可能会破坏现有的工作代码.我相信Eric Lippert有两个blog posts,更详细.

C#规范部分6.1.3(C#4规范)有此说法:

An implicit enumeration conversion
permits the decimal-integer-literal 0
to be converted to any enum-type and
to any nullable-type whose underlying
type is an enum-type. In the latter
case the conversion is evaluated by
converting to the underlying enum-type
and wrapping the result (§4.1.10).

这实际上表明该错误不仅仅是允许错误的类型,而是允许任何常量0值被转换,而不仅仅是字面值0.

编辑:它看起来像“恒定”部分是partially introduced in the C# 3 compiler.以前它是一些不变的值,现在看起来像是所有的.

相关文章

在要实现单例模式的类当中添加如下代码:实例化的时候:frmC...
1、如果制作圆角窗体,窗体先继承DOTNETBAR的:public parti...
根据网上资料,自己很粗略的实现了一个winform搜索提示,但是...
近期在做DSOFramer这个控件,打算自己弄一个自定义控件来封装...
今天玩了一把WMI,查询了一下电脑的硬件信息,感觉很多代码都...
最近在研究WinWordControl这个控件,因为上级要求在系统里,...