ttt*_*ppp 236 default switch-statement
在我的第一次代码审查(前一段时间)中,我被告知在所有switch语句中包含一个default子句是一种好习惯.我最近记得这个建议,但不记得理由是什么.这对我来说听起来很奇怪.
总是包含默认声明是否有合理的理由?
这种语言是依赖的吗?我不记得当时我用的是什么语言 - 也许这适用于某些语言而不适用于其他语言?
Van*_*ril 256
切换案例几乎总是有default案例.
使用a的原因 default
1.'抓住'意想不到的价值
switch(type)
{
case 1:
//something
case 2:
//something else
default:
// unknown type! based on the language,
// there should probably be some error-handling
// here, maybe an exception
}
Run Code Online (Sandbox Code Playgroud)
2.处理"默认"操作,其中案例用于特殊行为.
您在菜单驱动的程序和bash shell脚本中看到了很多.当变量在switch-case之外声明但未初始化时,您可能也会看到这一点,并且每个case都将其初始化为不同的值.这里默认需要初始化它,以便访问变量的行代码不会引发错误.
3.要向某人阅读您已经涵盖该案例的代码.
variable = (variable == "value") ? 1 : 2;
switch(variable)
{
case 1:
// something
case 2:
// something else
default:
// will NOT execute because of the line preceding the switch.
}
Run Code Online (Sandbox Code Playgroud)
这是一个过于简化的例子,但重点是有人阅读代码时不应该想知道为什么variable不能是1或2以外的东西.
我可以想到的唯一不使用的情况default是当交换机正在检查某些东西时,其中很明显可以忽略其他所有替代方案
switch(keystroke)
{
case 'w':
// move up
case 'a':
// move left
case 's':
// move down
case 'd':
// move right
// no default really required here
}
Run Code Online (Sandbox Code Playgroud)
Jar*_*lls 48
没有.
如果没有默认操作,上下文很重要.如果你只关心几个价值观会怎么样?
以读取游戏的按键为例
switch(a)
{
case 'w':
// Move Up
break;
case 's':
// Move Down
break;
case 'a':
// Move Left
break;
case 'd':
// Move Right
break;
}
Run Code Online (Sandbox Code Playgroud)
添加:
default: // Do nothing
Run Code Online (Sandbox Code Playgroud)
只是浪费时间并且无缘无故地增加代码的复杂性.
Adr*_*ith 42
无论你使用什么语言,我都会使用默认子句.
事情可以而且确实出错了.价值观将不是您所期望的,依此类推.
不想包含默认子句意味着您确信您知道可能的值集.如果您认为您知道可能值的集合,那么,如果该值超出了这组可能的值,您将希望被告知它 - 这肯定是一个错误.
这就是为什么你应该总是使用default子句并抛出错误的原因,例如在Java中:
switch (myVar) {
case 1: ......; break;
case 2: ......; break;
default: throw new RuntimeException("unreachable");
}
Run Code Online (Sandbox Code Playgroud)
没有理由包含更多信息而不仅仅是"无法访问"的字符串; 如果确实发生了这种情况,那么无论如何你都需要查看变量等的源和值,并且异常堆栈跟踪将包含该行号,因此不需要浪费时间将更多文本写入异常消息.
小智 41
没有默认情况在某些情况下实际上可能是有益的.
如果您的switch case是枚举值,没有默认情况,如果您缺少任何案例,则可以收到编译器警告.这样,如果将来添加新的枚举值并且您忘记在交换机中添加这些值的大小写,则可以在编译时找到有关该问题的信息.如果将无效值强制转换为枚举类型,您仍应确保代码对未处理的值采取适当的操作.因此,对于可以在枚举情况下返回而不是中断的简单情况,这可能最有效.
enum SomeEnum
{
ENUM_1,
ENUM_2,
// More ENUM values may be added in future
};
int foo(SomeEnum value)
{
switch (value)
{
case ENUM_1:
return 1;
case ENUM_2:
return 2;
}
// handle invalid values here
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Kur*_*tyn 13
在我的公司,我们为航空电子和国防市场编写软件,我们总是包含一个默认语句,因为必须明确处理switch语句中的所有情况(即使它只是一个评论说"什么也不做").我们无法承受软件只是行为不端或只是意外崩溃(甚至是我们认为不可能的)价值.
可以讨论的是,默认情况并不总是必要的,但是总是要求它,我们的代码分析器可以很容易地检查它.
Gab*_*abe 12
"switch"语句是否应始终包含默认子句?不应该.它通常应该包括默认值.
包含默认子句只有在有事情要做的情况下才有意义,例如断言错误条件或提供默认行为.包括一个"只是因为"是货物崇拜节目并没有提供任何价值.它的"开关"相当于说所有"if"语句都应该包含"else".
这是一个无关紧要的例子:
void PrintSign(int i)
{
switch (Math.Sign(i))
{
case 1:
Console.Write("positive ");
break;
case -1:
Console.Write("negative ");
break;
default: // useless
}
Console.Write("integer");
}
Run Code Online (Sandbox Code Playgroud)
这相当于:
void PrintSign(int i)
{
int sgn = Math.Sign(i);
if (sgn == 1)
Console.Write("positive ");
else if (sgn == -1)
Console.Write("negative ");
else // also useless
{
}
Console.Write("integer");
}
Run Code Online (Sandbox Code Playgroud)
据我所知,答案是"默认"是可选的,说开关必须始终包含默认值,就像说每个'if-elseif'必须包含'else'.如果默认情况下存在逻辑,那么'default'语句应该在那里,否则代码可以继续执行而不做任何事情.
我会说这取决于语言,但在C中,如果你打开一个枚举类型并且你处理每一个可能的值,你最好不要包括一个默认情况.这样,如果您稍后添加额外的枚举标记并忘记将其添加到交换机,那么合格的编译器会向您发出有关丢失案例的警告.
小智 5
我不同意上面 Vanwaril 投票最多的答案。
任何代码都会增加复杂性。还必须为此进行测试和记录。所以如果你能用更少的代码编程总是好的。我的观点是,我对非详尽的 switch 语句使用默认子句,而对详尽的 switch 语句不使用默认子句。为了确保我做对了,我使用了静态代码分析工具。那么让我们进入细节:
非详尽的 switch 语句:那些应该总是有一个默认值。顾名思义,这些语句并未涵盖所有可能的值。这也可能是不可能的,例如对整数值或字符串的 switch 语句。这里我想用Vanwaril的例子(需要说明的是,我认为他用这个例子提出了错误的建议。我在这里用它来说明相反的情况 --> 使用默认语句):
switch(keystroke)
{
case 'w':
// move up
case 'a':
// move left
case 's':
// move down
case 'd':
// move right
default:
// cover all other values of the non-exhaustive switch statement
}
Run Code Online (Sandbox Code Playgroud)
玩家可以按任何其他键。然后我们不能做任何事情(这可以通过在默认情况下添加注释来显示在代码中)或者它应该例如在屏幕上打印一些东西。这个案例是相关的,因为它可能发生。
详尽的 switch 语句:这些 switch 语句涵盖了所有可能的值,例如关于等级系统类型枚举的 switch 语句。第一次开发代码时,很容易覆盖所有值。然而,由于我们是人类,因此忘记一些的可能性很小。此外,如果您稍后添加一个枚举值,以便所有 switch 语句都必须进行调整以使其详尽无遗,则会再次打开通往错误地狱的道路。简单的解决方案是静态代码分析工具。该工具应检查所有 switch 语句并检查它们是否详尽无遗或它们是否具有默认值。这是一个详尽的 switch 语句的示例。首先我们需要一个枚举:
public enum GradeSystemType {System1To6, SystemAToD, System0To100}
Run Code Online (Sandbox Code Playgroud)
然后我们需要这个枚举的变量,比如GradeSystemType type = .... 一个详尽的 switch 语句将如下所示:
switch(type)
{
case GradeSystemType.System1To6:
// do something
case GradeSystemType.SystemAToD:
// do something
case GradeSystemType.System0To100:
// do something
}
Run Code Online (Sandbox Code Playgroud)
所以如果我们扩展GradeSystemType例如System1To3静态代码分析工具应该检测到没有 default 子句并且 switch 语句不是详尽的,所以我们保存。
只是一件事。如果我们总是使用一个default子句,那么静态代码分析工具可能无法检测详尽或非详尽的 switch 语句,因为它总是检测到该default子句。这是非常糟糕的,因为如果我们将枚举扩展为另一个值而忘记将其添加到一个 switch 语句中,我们将不会收到通知。
| 归档时间: |
|
| 查看次数: |
203409 次 |
| 最近记录: |