首页 新闻 会员 周边

求助,C# switch下|号的作用,非常奇怪为什么我的代码会报错?

0
悬赏园豆:100 [已解决问题] 解决于 2014-06-24 18:24
   //故事从这里开始,这是参考的代码:注意这里的第一句,使用了|
   case ValidateType.IsEmpty | ValidateType.MinLength | ValidateType.MaxLength:
          if (null == value || value.ToString().Length < 1) 
        goto case ValidateType.IsEmpty;
          goto case ValidateType.MinLength | ValidateType.MaxLength;

  我根据如上代码,写了一套枚举,然后switch这个枚举,和这段代码采用了相同的做法,我的代码却报错,代码如下:

 switch (attr.ValidateType)
 {
     case ValidateType.Empty:
         break;
     case ValidateType.MaxLength:
         break;
     //这个case报错,标签case 2:已经出现在该switch语句中
     case ValidateType.Empty | ValidateType.MaxLength:
         break;
}

  但是我写另外一段case却又不报错,代码如下:

switch (attr.ValidateType)
{
    case ValidateType.Phone:
        break;
    case ValidateType.Email:
        break;
    case ValidateType.Phone | ValidateType.Email:
        break;
}

  经过测试,发现和枚举有关,这样的枚举的结构,Phone和Email的case不报错,但是如果中间补上索引2的话(索引连贯起来),就会报错:

    public enum ValidateType
    {
        Empty = 0,
        MaxValue = 1,
        //...真正代码中间有很多,这里删除了很多,注意枚举少了2
        //但是如果中间有一个枚举2的话
        //那么case ValidateType.Phone | ValidateType.Email:也会报错
        Phone = 3,
        Email = 4
    }

  看起来好像可以有眉目。 

  但是真正的代码中枚举都是连贯的,中间没有缺过某个索引,一直索引到12的,

  Empty=0,MaxValue=1,中间是连贯的索引,Phone=7,Email=8。

  而在这样连贯索引的情况下,第一个switch照样报错,第二个switch却没有报错。

  根本就无法理解为什么,不求解答出这个问题,但求了解switch中|号的作用

linkFly的主页 linkFly | 初学一级 | 园豆:91
提问于:2014-06-23 23:34
< >
分享
最佳答案
2

switch里使用的就是int型而已,如果需要用|符号,那么需要在定义ValidateType的时候,使用0、1、2、4、8、16这种值,这样不管那几个枚举值相与,都不会得到相同的int型的值,在switch里也就不会出错了

你上面出错的代码

 switch (attr.ValidateType)
 {
     case ValidateType.Empty:
         break;
     case ValidateType.MaxLength:
         break;
     //这个case报错,标签case 2:已经出现在该switch语句中
     case ValidateType.Empty | ValidateType.MaxLength:
         break;
}

在编译器看来是下面这样的

 switch (attr.ValidateType)
 {
     case 0:
         break;
     case 1:
         break;
     //这个case报错,标签case 2:已经出现在该switch语句中
     case 1:
         break;
}

当然出错了

收获园豆:65
诶碧司 | 小虾三级 |园豆:1912 | 2014-06-24 10:29

为什么0、1、2、4、8、16这种值不会报错?小弟入门太浅,能给解释下么?万分感谢。

linkFly | 园豆:91 (初学一级) | 2014-06-24 10:48

@linkFly: 仔细看看,你会发现这些都是2的倍数

NET_zhaoqiang | 园豆:296 (菜鸟二级) | 2014-06-24 11:06

@linkFly: 除了0之外,其它的值任意几个相或,都不会变成枚举值,如1|4|8,会变成13,2|4=6等,都不会和原来的1、2、4、8这些值冲突

其实你如果把这些值变为二进制就更明显了

诶碧司 | 园豆:1912 (小虾三级) | 2014-06-24 11:33
其他回答(6)
0

1、你的两个对比的代码在什么地方能够用到么,在真实的情况下是不会用到的,因为你的上面已经出现过了。

2、

case ValidateType.Empty:

case ValidateType.MaxLength:

   break;

这样写就可以解决了,还通俗易懂!

刘宏玺 | 园豆:14020 (专家六级) | 2014-06-23 23:47
1

没那么可怕,而且编译器的错误提示也很明确。首先你要明白两点:

1、case 标签不能重复;

2、| 是或运算符。

 

case ValidateType.Empty | ValidateType.MaxLength: 等价于:

ValidateType vt = ValidateType.Empty | ValidateType.MaxLength;

case vt:

收获园豆:10
Launcher | 园豆:45045 (高人七级) | 2014-06-24 08:16

|号不是“或”运算,位枚举里,可以某种程度上理解为“并且”。

支持(0) 反对(0) linkFly | 园豆:91 (初学一级) | 2014-06-24 10:42

@linkFly: 你可以这么理解,但是编译器不是这么理解的。从语法上讲 case 是常量表达式,因此其后跟随的一定是个常量。因为你的错误理解,导致你的出这样的疑问:

 

那您知道为什么0、1不能用|,而3、4,7、8为什么可以用|?

你先做完或运算,然后在解析 case 语句,你就知道错在哪里了。

支持(0) 反对(0) Launcher | 园豆:45045 (高人七级) | 2014-06-24 11:08

@Launcher: 知道了什么意思,是我对位域不够了解,不好意思。

支持(0) 反对(0) linkFly | 园豆:91 (初学一级) | 2014-06-24 13:21
0

你需要为你的枚举类型加上 [Flags]

收获园豆:10
Haart | 园豆:212 (菜鸟二级) | 2014-06-24 09:11

非常感谢,根据flags找到了很多相关的资料,大部分疑惑都解开了。

那您知道为什么0、1不能用|,而3、4,7、8为什么可以用|?

支持(0) 反对(0) linkFly | 园豆:91 (初学一级) | 2014-06-24 10:46
0

你的逻辑走下来不对啊,因为一旦attr.ValidateType=ValidateType.Empty,那他进行完一个case之后,就会break走了,根本不会在往下执行,所以你写在ValidateType.Empty | ValidateType.MaxLength就不可能执行,你的代码就有风险,可能没有按照你的预期执行,所以程序报错

飞来飞去 | 园豆:2057 (老鸟四级) | 2014-06-24 09:46

这个case是ValidateType.Empty和ValidateType.MaxLength的并集。

支持(0) 反对(0) linkFly | 园豆:91 (初学一级) | 2014-06-24 10:48

@linkFly: 对不起没注意是|

支持(0) 反对(0) 飞来飞去 | 园豆:2057 (老鸟四级) | 2014-06-24 11:53
0

 他的提示这么明确了```就是重复了.

而且这个是位或运算.不太明白你的做法

吴瑞祥 | 园豆:29449 (高人七级) | 2014-06-24 09:58
1

这个是因为枚举类中枚举值导致的问题。|是按位或运算。如0|1 =1 其实是 0000 0000 | 0000 0001 = 0000 0001。

0,1,2,4,8,16,2^x的二进制是0000 0000, 0000 0001, 0000 0010, 0000 0100, 这种按位或运算下来除了0|1会与1重复外其他都不会,所以不会出问题了。

收获园豆:15
jecofang | 园豆:560 (小虾三级) | 2014-06-24 16:54
清除回答草稿
   您需要登录以后才能回答,未注册用户请先注册