int到enum的转换无效

本文关键字:转换 无效 enum int | 更新日期: 2023-09-27 17:57:52

我正在测试我写的一些代码,想知道是否需要默认的案例处理。

让我们像这个一样定义MyEnum

public enum MyEnum 
{
    [Description("Value")]
    Value = 0,
    [Description("Other value")]
    OtherValue = 1,
}

我问自己的逻辑与此类似:

MyEnum val = (MyEnum)8;
if(val == MyEnum.Value)
    //do stuff
else if (val == MyEnum.OtherValue)
    //do other stuff
else 
    throw new ArgumentException("The value is not currently supported");

我的理由是没有默认情况,因为从枚举中未定义的值进行的强制转换无论如何都会在被我的代码捕获之前引发异常。

所以我试了一下我在这里的例子,令我惊讶的是,演员们没有抛出任何异常,这是我默认的案件处理女巫抛出的异常。

我的问题是:为什么任何intMyEnum的强制转换都是有效的?我知道在这个示例中,Enum的基本值是int,但我本希望从强制转换中抛出异常。为什么这是有效的?

int到enum的转换无效

枚举只是处理底层数据类型(默认情况下为Int32)值的一种奇特方法。你得到了命名值,你就失去了数学运算。没有规定只有声明中命名的值才是有效值,因此不会出现异常或编译器错误。

当您使用枚举作为标志时,这一点变得非常明显。

[Flags]
public enum Something
{
   Foo = 1,
   Bar = 2,
   Baz = 4
}

现在像这个

var x = Something.Foo | Something.Bar; // The value is 1 | 4 = 5

是绝对好的,而且你可以有你从未命名过的值。这一切都归结为你错误的假设,即允许的值集在某种程度上受到了限制,正如引用规范的其他答案所指出的那样,事实并非如此。

这是经过设计的。参见C#规范4.1.9枚举类型:

枚举类型是具有命名常量的不同类型。枚举类型的值集与基础类型的值。枚举类型的值不是将限制为命名常量的值。

实际上,枚举只是一组命名的文本字段(它们是枚举类型的命名常量)和一个保存枚举实例值的特殊字段:

.class public auto ansi sealed MyEnum
    extends [mscorlib]System.Enum  
{
    .field public static literal valuetype Namespace.MyEnum Value = int32(0)
    .field public static literal valuetype Namespace.MyEnum OtherValue = int32(1)
    .field public specialname rtspecialname int32 value__
}

正如您所看到的,这是一个底层类型的简单字段,任何Int32值都可以分配给枚举变量。

规范描述了这种行为:

14.5枚举值和操作

枚举类型可以接受的值集不受其枚举成员。特别是enum可以强制转换为enum类型,并且是该枚举类型。