只要我记得我已经避免使用switch语句.实际上,我不记得它曾经进入我的意识作为一种可能的做事方式,因为它早在我的头脑中钻了它只不过是转换语句中的一个错误.然而,今天我遇到了一些在设计中使用它的代码,这让我立刻想知道社区中的每个人都认为有关switch语句的漏洞.
这是编程语言应该明确不允许的东西(比如C#,但它提供了一种解决方法),还是任何语言的功能都足以留给程序员手中?
编辑: 我没有具体到达我的意思.我经常使用这种类型:
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something
break;
case 2:
case 3:
case 4:
// Do something
break;
}
但是,我很担心这样的事情.
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something but fall through to the other cases
// after doing it.
case 2:
case 3:
case 4:
// Do something else.
break;
}
这种方式只要大小写为0,1就会在switch语句中执行所有操作.我已经通过设计看到了这一点,我只是不知道我是否同意以这种方式使用switch语句.我认为第一个代码示例非常有用且安全.第二个似乎有点危险.
这可能取决于您认为的漏洞.我对这种事情很满意:
switch (value)
{
case 0:
result = ZERO_DIGIT;
break;
case 1:
case 3:
case 5:
case 7:
case 9:
result = ODD_DIGIT;
break;
case 2:
case 4:
case 6:
case 8:
result = EVEN_DIGIT;
break;
}
但如果你有一个案例标签,后面跟着另一个案例标签的代码,我几乎总是认为这是邪恶的.也许将公共代码移动到一个函数并从两个地方调用将是一个更好的主意.
请注意我使用的C++ FAQ定义 "邪恶"
这是一把双刃剑.有时非常有用,通常很危险.
什么时候好?当你想要10个案例都以同样的方式处理...
switch (c) { case 1: case 2: ... do some of the work ... /* FALLTHROUGH */ case 17: ... do something ... break; case 5: case 43: ... do something else ... break; }
我喜欢的一条规则是,如果你做任何想要排除休息的事情,你需要一个明确的评论/*FALLTHROUGH*/表示这是你的意图.
根据你正在做的事情,堕落真的很方便.考虑这种安排和可理解的方式来安排选项:
switch ($someoption) { case 'a': case 'b': case 'c': // do something break; case 'd': case 'e': // do something else break; }
想象一下用if/else做这件事.这将是一个烂摊子.
你听说过Duff的设备吗?这是使用switch fallthrough的一个很好的例子.
这是一个可以使用的功能,它可以像几乎所有语言功能一样被滥用.
它可能是非常有用的几次,但一般来说,没有穿透是期望的行为.应该允许通过,但不是隐含的.
例如,更新某些数据的旧版本:
switch (version) { case 1: // update some stuff case 2: // update more stuff case 3: // update even more stuff case 4: // and so on }
我喜欢在开关中使用不同的回退语法,比如,errr ..
switch(myParam) { case 0 or 1 or 2: // do something; break; case 3 or 4: // do something else; break; }
注意:如果你使用标志声明你的枚举上的所有案例,那么枚举就已经可以了吗?听起来也不是那么糟糕,案件可能(应该?)很好地成为你的枚举的一部分.
对于使用扩展方法的流畅界面,这可能是一个很好的案例(没有双关语)?有点像,错误......
int value = 10; value.Switch() .Case(() => { /* do something; */ }, new {0, 1, 2}) .Case(() => { /* do something else */ } new {3, 4}) .Default(() => { /* do the default case; */ });
虽然这可能更不易读:P
与任何事情一样:如果小心使用,它可以是一个优雅的工具.
但是,我认为缺点不仅仅是不使用它,最后也不再允许它(C#).问题包括:
很容易"忘记"休息
对于代码维护者来说,并不总是显而易见的是,省略的中断是故意的
很好地利用了开关/外壳:
switch (x) { case 1: case 2: case 3: do something break; }
BAAAAAD使用开关/案例:
switch (x) { case 1: some code case 2: some more code case 3: even more code break; }
在我看来,这可以使用if/else结构重写,完全没有任何损失.
我的最后一句话:远离BAD示例中的堕落案例标签,除非您使用这种风格并且很好理解这些样式的遗留代码.