为什么C#3允许将文字零(0)隐式转换为任何枚举?

为什么C#3允许将文字零(0)隐式转换为任何枚举?,c#,c#-3.0,C#,C# 3.0,C#3(Visual Studio 2008)对语言引入了一个突破性的更改(,请参见更改12),允许将任何文本零隐式转换为枚举。这在许多方面似乎很奇怪。有人知道为什么这是规范的一部分吗?为什么不是字面意义上的呢?还是七点?为什么零号特别?它做出了一些非常违反直觉的过载分辨率选择。比如说 function string F(object o) { return o.ToString(); } function string F(DbType t) { return t.ToString(); }

C#3(Visual Studio 2008)对语言引入了一个突破性的更改(,请参见更改12),允许将任何文本零隐式转换为枚举。这在许多方面似乎很奇怪。有人知道为什么这是规范的一部分吗?为什么不是字面意义上的呢?还是七点?为什么零号特别?它做出了一些非常违反直觉的过载分辨率选择。比如说

function string F(object o) { return o.ToString(); }
function string F(DbType t) { return t.ToString(); }
int i = 0;
F((long)0) == "String" // would have been "0" in VS 2005
F(0) == "String"
F(i) == "0"

非常混乱,并且故意对语言进行了破坏性的更改。有什么想法吗?

从1.0版开始就允许了。它是枚举的默认值

“文本0是隐式可转换的 任何枚举类型。在Visual C#2005中 以及早期版本的编译器, 还有一些常数 计算结果为0的表达式 可以隐式转换为任何枚举 类型,但确定 以下哪个表达式是 不清楚。在Visual C中# 2008年,所有不变的表达 都可以隐式地表示为0 已转换为任何枚举类型。“


我猜这是因为0被认为是枚举的“默认值”

C#(默认关键字是在C#2.0中引入的)

产出:

True
True
C#始终允许将文字0隐式转换为任何枚举值。改变的是规则如何应用于其他常量表达式。使其更加一致,并允许任何计算结果为0的常量表达式隐式转换为枚举

您给出的示例在所有版本的C#中产生相同的行为

下面是一个已更改行为的示例(直接来自)

Visual C#2005输出:

0=>A(枚举E) (int)E.Zero=>A(对象) Visual C#2008输出:

0=>A(枚举E) (int)E.Zero=>A(枚举E)
“枚举元素的默认基础类型为int。默认情况下,第一个枚举数的值为0,每个后续枚举数的值增加1。”-这是从,所以一直如此。

正如其他人所提到的,0是默认枚举。尝试按以下方式考虑枚举(以更明确的方式):


由于给定枚举的值不明确,C#将自动为其指定一个默认值。如果您不想这样做,那么您必须明确定义给定枚举的值。

啊,这是一个很好的观点。我们应用程序中的示例实际上是程序员使用(long)0的地方。也许在早期版本中,它没有触发“常量表达式”规则。问题仍然存在:如果没有其他整数可以隐式转换为枚举,那么为什么枚举数为零?@Sebastian,我不确定这一点。可能有一个非常有趣的语言原因,希望Eric稍后会对此发表评论。常量表达式是任何可以在编译时确定为常量值的表达式(表达式结果的值可以在源代码中替换,没有副作用)。在VS 2005中,只有“文字”零被隐式转换为枚举,而在>=VS 2008中,任何计算结果为零的“常量表达式”都将被隐式转换。我认为这非常准确,因为
default(T)
在1.0中不存在,他们不想在语言中出现不一致的情况,即可以隐式地将枚举变量默认值初始化为
0
,但不能显式地初始化(无需强制转换)。@Pavel Minaev——我喜欢这个理论。如果你要对一个问题(特别是已经投票支持答案的问题)进行如此剧烈的更改,对于回答者、浏览器和您来说,最好创建一个新问题。现在,您将获得两个不同问题的答案,第一个问题可能是普通浏览器在编辑历史中永远不会看到的。就像魔术一样,这个问题已被编辑回其原始误导形式!需要注意的是,在VS 2008中,给出的样本没有被破坏。我会做出改变,看看它是否能坚持下去。。。
True
True
public enum E
{
    Zero = 0,
    One = 1,
} 

class A
{
    public static A(string s, object o)
    { System.Console.WriteLine("{0} => A(object)", s); } 

    public static A(string s, E e)
    { System.Console.WriteLine("{0} => A(Enum E)", s); }

    static void Main()
    {
        A a1 = new A("0", 0);
        A a3 = new A("(int) E.Zero", (int) E.Zero);
    }
}
0 => A(Enum E) (int) E.Zero => A(object) 0 => A(Enum E) (int) E.Zero => A(Enum E)
public enum HairColor
{
    Blonde           = 0x0000;
    Brunett          = 0x0001;
    Red              = 0x0002;
    StrawberryBlonde = 0x0004;
}