为什么我不能通过单个隐式转换为枚举来打开类

时间:2009-12-09 03:48:56

标签: c# switch-statement enums

我想知道为什么单个隐式转换为枚举值的方式与转换为系统类型时的方式不同。我看不出任何技术上的原因,但也许有人比我更聪明,可以帮助我。

跟进无法使用"A value of an integral type expected""Cannot implicitly convert type 'Test.En' to 'Test.Foo"进行编译。

void test1 (){
    Foo f = new Foo();

    switch (f)         // Comment this line to compile
    //switch ((En)f)   // Uncomment this line to compile
    {
        case En.One:
            break;
    }
}


//////////////////////////////////////////////////////////////////

public enum En
{
    One,
    Two,
    Three,
}

public class Foo
{
    En _myEn;

    public static implicit operator En(Foo f)
    {
        return f._myEn;
    }
}
来自规范的

编辑

switch语句的控制类型由switch表达式建立。如果switch表达式的类型是 sbyte,byte,short,ushort,int,uint,long,ulong,char,string或enum-type ,那么这就是交换机的控制类型声明。否则,从switch表达式的类型到以下可能的管理类型之一,必须存在一个用户定义的隐式转换(第6.4节): sbyte,byte,short,ushort,int,uint,long,ulong, char,string 。如果不存在此类隐式转换,或者存在多个此类隐式转换,则会发生编译时错误。

澄清问题,为什么 enum-type 未包含在允许的用户定义的隐式转换列表中?

5 个答案:

答案 0 :(得分:5)

语言设计说明存档不能为此决定提供理由。这是不幸的,因为决定已经改变。如您所见,设计随着时间的推移而发展:

1999年5月26日的笔记:

  

允许使用哪些类型   switch语句的参数?   整数类型包括char,enum   类型,布尔。 C#也允许类型   这可以隐含地和   毫不含糊地转换为其中之一   上述类型。 (如果有   多个隐式转换,然后它   模糊和编译时错误   发生。)我们不确定我们是否   想要支持字符串。

1999年6月7日:

  

我们讨论过启用字符串的开关   参数。我们认为这很好   功能 - 语言可以增加价值   通过使这种常见情况更容易   写,以及额外的复杂性   对于用户来说非常低。

1999年12月20日:

  

打开电源是违法的   表达类型bool。这是合法的   打开一个表达式   整数类型或字符串类型。它是   合法地打开一个表达式   只有一个隐式的类型   转换为整数类型或   字符串类型。

这里我们首次出现了相关规则。 Enum似乎已经消失了。为什么不使用用户定义的隐式转换来枚举?这只是一个疏忽吗?设计师没有记录他们的想法。

请注意,第一句不是我们实施的。我不清楚为什么实现者与设计委员会推荐的相反。几年之后,这在笔记中再次出现:

2003年8月13日:

  

编译器允许打开bool。   不想记录并添加它   对语言。不想删除   出于兼容性原因。决定   默默地继续支持切换   在布尔。

我觉得这很傻;当我们制作C#3.0规范的注释印刷版时,我将bool(和bool?)添加到法律管理类型列表中。

简而言之:整件事情有点混乱。我不知道为什么枚举进入,然后出局,然后是半成半。这可能必须是未知之谜之一。

答案 1 :(得分:2)

因为枚举被视为整数以便切换,并且正如我之前所问的那样the compiler doesn't do multiple implicit conversions to get to a usable type,它无法弄清楚如何启用foo。

关于为什么枚举不能像这样使用的唯一理论是枚举本身不是整数类型,因此编译器必须进行多次隐式转换才能从foo获取整数原语。

我编译然后反映了你的代码,结果如下:

public static void Main()
{
    Foo f = new Foo();
    f._myEn = En.Three;
    switch (f)
    {
        case En.One:
        {
        }
    }
}

显然,在封面下,它确实进行了隐式转换。 :S

答案 2 :(得分:0)

void test1 (){
   Foo f = new Foo();
   En n = f;

    switch (n)
    {
        case En.One:
            break;
    }
}

编辑:由于switch需要一个整数值,因此编写switch(f)会使编译器寻找从Foo的实例转换为不存在的整数类型。

答案 3 :(得分:-1)

看一下第二条错误消息。编译器正在尝试对枚举进行类型强制以匹配switch语句中的类型。

作为一个兴趣点,这是怎么回事?

void test2 (){
    Foo f = new Foo();

    switch (En.One)
    {
        case f:
            break;
    }
}

答案 4 :(得分:-1)

如果您的类包含两个枚举并且两者都有隐式转换运算符,该怎么办?或者更好的是,如果你有enum和int的隐式转换运算符怎么办?编写switch语句时,编译器会“自动”为您选择哪种转换?

您必须明确指定switch语句中正在使用的对象类型。隐式运算符只是告诉编译器/运行时“如果你有一个Foo并且需要一个En,这个代码就是这样”。它不会更改对象的实际基础类型。