Fos*_*tah 109 coding-style switch-statement
只要我记得我已经避免使用switch语句.实际上,我不记得它曾经进入我的意识作为一种可能的做事方式,因为它早在我的头脑中钻了它只不过是转换语句中的一个错误.然而,今天我遇到了一些在设计中使用它的代码,这让我立刻想知道社区中的每个人都认为有关switch语句的漏洞.
这是编程语言应该明确不允许的东西(比如C#,但它提供了一种解决方法),还是任何语言的功能都足以留给程序员手中?
编辑: 我没有具体到达我的意思.我经常使用这种类型:
switch(m_loadAnimSubCt){
case 0:
case 1:
// Do something
break;
case 2:
case 3:
case 4:
// Do something
break;
}
Run Code Online (Sandbox Code Playgroud)
但是,我很担心这样的事情.
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;
}
Run Code Online (Sandbox Code Playgroud)
这种方式只要大小写为0,1就会在switch语句中执行所有操作.我已经通过设计看到了这一点,我只是不知道我是否同意以这种方式使用switch语句.我认为第一个代码示例非常有用且安全.第二个似乎有点危险.
Fre*_*son 82
这可能取决于您认为的漏洞.我对这种事情很满意:
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;
}
Run Code Online (Sandbox Code Playgroud)
但如果你有一个案例标签,后面跟着另一个案例标签的代码,我几乎总是认为这是邪恶的.也许将公共代码移动到一个函数并从两个地方调用将是一个更好的主意.
Joh*_*n M 51
这是一把双刃剑.有时非常有用,通常很危险.
什么时候好?当你想要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;
}
Run Code Online (Sandbox Code Playgroud)
我喜欢的一条规则是,如果你做任何想要排除休息的事情,你需要一个明确的评论/*FALLTHROUGH*/表示这是你的意图.
Luc*_*man 20
根据你正在做的事情,堕落真的很方便.考虑这种安排和可理解的方式来安排选项:
switch ($someoption) {
case 'a':
case 'b':
case 'c':
// do something
break;
case 'd':
case 'e':
// do something else
break;
}
Run Code Online (Sandbox Code Playgroud)
想象一下用if/else做这件事.这将是一个烂摊子.
小智 10
它可能是非常有用的几次,但一般来说,没有穿透是期望的行为.应该允许通过,但不是隐含的.
例如,更新某些数据的旧版本:
switch (version) {
case 1:
// update some stuff
case 2:
// update more stuff
case 3:
// update even more stuff
case 4:
// and so on
}
Run Code Online (Sandbox Code Playgroud)
它强大而危险。失败的最大问题是它不明确。例如,如果您遇到经常编辑的代码,其中包含带有失败的开关,您如何知道这是故意的而不是错误?
无论我在哪里使用它,我都会确保对其进行正确的注释:
switch($var) {
case 'first':
// Fall-through
case 'second':
i++;
break;
}
Run Code Online (Sandbox Code Playgroud)
我喜欢在开关中使用不同的回退语法,比如,errr ..
switch(myParam)
{
case 0 or 1 or 2:
// do something;
break;
case 3 or 4:
// do something else;
break;
}
Run Code Online (Sandbox Code Playgroud)
注意:如果你使用标志声明你的枚举上的所有案例,那么枚举就已经可以了吗?听起来也不是那么糟糕,案件可能(应该?)很好地成为你的枚举的一部分.
对于使用扩展方法的流畅界面,这可能是一个很好的案例(没有双关语)?有点像,错误......
int value = 10;
value.Switch()
.Case(() => { /* do something; */ }, new {0, 1, 2})
.Case(() => { /* do something else */ } new {3, 4})
.Default(() => { /* do the default case; */ });
Run Code Online (Sandbox Code Playgroud)
虽然这可能更不易读:P
与任何事情一样:如果小心使用,它可以是一个优雅的工具.
但是,我认为缺点不仅仅是不使用它,最后也不再允许它(C#).问题包括:
很好地利用了开关/外壳:
switch (x)
{
case 1:
case 2:
case 3:
do something
break;
}
Run Code Online (Sandbox Code Playgroud)
BAAAAAD使用开关/案例:
switch (x)
{
case 1:
some code
case 2:
some more code
case 3:
even more code
break;
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这可以使用if/else结构重写,完全没有任何损失.
我的最后一句话:远离BAD示例中的堕落案例标签,除非您使用这种风格并且很好理解这些样式的遗留代码.
像第一个例子一样使用失败显然是可以的,我不认为它是真正的失败。
第二个例子是危险的并且(如果没有广泛评论的话)不明显。我教我的学生不要使用这样的结构,除非他们认为值得花精力为其添加注释块,该注释块描述了这是故意的失败,以及为什么该解决方案比其他解决方案更好。这可以防止草率使用,但在使用它来获得优势的情况下仍然允许使用。
这或多或少相当于我们在太空项目中当有人想要违反编码标准时所做的事情:他们必须申请豁免(我被要求就裁决提供建议)。