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

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


当前回答

如果开关值(switch(variable))不能达到默认情况,则根本不需要默认情况。即使我们保留默认情况,它也不会被执行。这是死代码。

其他回答

这是一个可选的编码“约定”。是否需要取决于用途。我个人认为,如果你不需要它,它就不应该在那里。为什么要包含一些用户不会使用或接触到的内容?

如果情况的可能性是有限的(即一个布尔值),那么默认子句是多余的!

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”语句都应该包含一个“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在特定语言中的工作方式,但是在大多数语言中,当没有匹配到case时,switch语句的执行就会毫无警告地结束。想象一下,你期望得到一组值,并在switch中处理它们,然而你在输入中得到了另一个值。什么都没发生,你也不知道什么都没发生。如果您发现了违约情况,您就会知道有问题。

我相信这是特定于语言的,对于c++来说是枚举类类型的一个次要问题。这似乎比传统的C enum更安全。但

如果你看一下std::byte的实现,它是这样的:

enum class byte : unsigned char {} ;

来源:https://en.cppreference.com/w/cpp/language/enum

再想想这个:

否则,如果T是一个枚举类型,它的作用域是或 具有固定底层类型的无作用域,如果带括号的init-list具有 只有一个初始化式,如果从初始化式转换为 基础类型是非窄化的,如果初始化为 -直接列表初始化,然后使用 将初始化式转换为其基础类型的结果。 (因为c++ 17)

来源:https://en.cppreference.com/w/cpp/language/list_initialization

这是一个枚举类的例子,表示的值不是定义的枚举值。由于这个原因,您不能完全信任枚举。根据应用的不同,这一点可能很重要。

然而,我真的很喜欢@Harlan Kassler在他的帖子里说的话,我自己也会在某些情况下开始使用这个策略。

这是一个不安全枚举类的例子:

enum class Numbers : unsigned
{
    One = 1u,
    Two = 2u
};

int main()
{
    Numbers zero{ 0u };
    return 0;
}