在我的第一次代码评审中(不久前),有人告诉我,在所有switch语句中包含一个default子句是一种很好的实践。我最近想起了这个建议,但不记得理由是什么了。现在我听起来很奇怪。

是否有一个合理的理由总是包含默认语句? 这是语言依赖吗?我不记得当时我在用什么语言了——也许这适用于一些语言而不是其他语言?


当前回答

我总是会使用默认子句,无论您使用哪种语言。

事情会出错,也确实会出错。价值观不会是你所期望的,等等。

不想包含默认子句意味着您确信自己知道可能的值集。如果你相信你知道这个可能值的集合,那么如果这个值在这个可能值的集合之外,你会想要知道它-这当然是一个错误。

这就是为什么你应该总是使用默认子句并抛出错误的原因,例如在Java中:

switch (myVar) {
   case 1: ......; break;
   case 2: ......; break;
   default: throw new RuntimeException("unreachable");
}

除了“unreachable”字符串之外,没有理由包含更多信息;如果它真的发生了,无论如何您都需要查看源代码和变量的值等,异常堆栈跟踪将包括该行号,因此不需要浪费时间在异常消息中写入更多文本。

其他回答

switch语句应该总是包含一个默认子句吗? 不存在缺省情况下的开关情况,在缺省情况下,当不匹配任何其他case值时,将触发开关值开关(x)。

您应该有一个默认值来捕捉传入的非预期值。

然而,我不同意Adrian Smith关于默认的错误消息应该是完全没有意义的。可能会有一个你没有预见到的未处理的情况(这是一点),你的用户最终会看到,像“无法到达”这样的消息是完全没有意义的,在这种情况下对任何人都没有帮助。

举个例子,你有多少次经历过毫无意义的蓝皮书?或者致命异常@ 0x352FBB3C32342?

No.

如果没有默认操作,那么上下文就很重要了。如果你只关心几个价值怎么办?

以读取游戏按键为例

switch(a)
{
   case 'w':
     // Move Up
     break;
   case 's':
     // Move Down
     break;
   case 'a':
     // Move Left
     break;
   case 'd':
     // Move Right
     break;
}

添加:

default: // Do nothing

只是浪费时间,毫无理由地增加了代码的复杂性。

在我的公司,我们为航空电子设备和国防市场编写软件,我们总是包含一个默认语句,因为switch语句中的所有情况都必须显式处理(即使它只是一个说“什么都不做”的注释)。我们不能让软件只是行为不端,或者仅仅是在意外值(甚至是我们认为不可能的值)上崩溃。

可以讨论的是,默认情况并不总是必要的,但通过总是需要它,我们的代码分析人员很容易检查它。

在某些情况下,没有默认情况实际上是有益的。

If your switch cases are enums values, by not having a default case, you can get a compiler warning if you are missing any cases. That way, if new enum values are added in the future and you forget to add cases for these values in the switch, you can find out about the problem at compile time. You should still make sure the code takes appropriate action for unhandled values, in case an invalid value was cast to the enum type. So this may work best for simple cases where you can return within the enum case rather than break.

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;
 }