//故事从这里开始,这是参考的代码:注意这里的第一句,使用了| 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中|号的作用
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; }
当然出错了
为什么0、1、2、4、8、16这种值不会报错?小弟入门太浅,能给解释下么?万分感谢。
@linkFly: 仔细看看,你会发现这些都是2的倍数
@linkFly: 除了0之外,其它的值任意几个相或,都不会变成枚举值,如1|4|8,会变成13,2|4=6等,都不会和原来的1、2、4、8这些值冲突
其实你如果把这些值变为二进制就更明显了
1、你的两个对比的代码在什么地方能够用到么,在真实的情况下是不会用到的,因为你的上面已经出现过了。
2、
case ValidateType.Empty:
case ValidateType.MaxLength:
break;
这样写就可以解决了,还通俗易懂!
没那么可怕,而且编译器的错误提示也很明确。首先你要明白两点:
1、case 标签不能重复;
2、| 是或运算符。
case ValidateType.Empty | ValidateType.MaxLength: 等价于:
ValidateType vt = ValidateType.Empty | ValidateType.MaxLength;
case vt:
|号不是“或”运算,位枚举里,可以某种程度上理解为“并且”。
@linkFly: 你可以这么理解,但是编译器不是这么理解的。从语法上讲 case 是常量表达式,因此其后跟随的一定是个常量。因为你的错误理解,导致你的出这样的疑问:
那您知道为什么0、1不能用|,而3、4,7、8为什么可以用|?
你先做完或运算,然后在解析 case 语句,你就知道错在哪里了。
@Launcher: 知道了什么意思,是我对位域不够了解,不好意思。
你需要为你的枚举类型加上 [Flags]
非常感谢,根据flags找到了很多相关的资料,大部分疑惑都解开了。
那您知道为什么0、1不能用|,而3、4,7、8为什么可以用|?
你的逻辑走下来不对啊,因为一旦attr.ValidateType=ValidateType.Empty,那他进行完一个case之后,就会break走了,根本不会在往下执行,所以你写在ValidateType.Empty | ValidateType.MaxLength就不可能执行,你的代码就有风险,可能没有按照你的预期执行,所以程序报错
这个case是ValidateType.Empty和ValidateType.MaxLength的并集。
@linkFly: 对不起没注意是|
他的提示这么明确了```就是重复了.
而且这个是位或运算.不太明白你的做法
这个是因为枚举类中枚举值导致的问题。|是按位或运算。如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重复外其他都不会,所以不会出问题了。