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

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


当前回答

“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");
}

这相当于:

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

其他回答

“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");
}

这相当于:

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

开关情况几乎总是有一个默认情况。

使用默认值的原因

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
}

2. 处理“默认”操作,其中的case是针对特殊行为的。

您在菜单驱动程序和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.
}

这是一个过于简化的例子,但关键是阅读代码的人不应该怀疑为什么变量不能是1或2以外的东西。


我能想到的唯一不使用默认值的情况是,当开关正在检查一些非常明显的东西时,其他选项都可以愉快地忽略

switch(keystroke)
{
    case 'w':
        // move up
    case 'a':
        // move left
    case 's':
        // move down
    case 'd':
        // move right
    // no default really required here
}

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

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

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

我会说这取决于语言,但在C中,如果你要打开一个枚举类型并处理每个可能的值,最好不要包含默认大小写。这样,如果您稍后添加了一个额外的enum标记,并且忘记将其添加到交换机中,称职的编译器将会就缺少的大小写向您发出警告。