在我的第一次代码评审中(不久前),有人告诉我,在所有switch语句中包含一个default子句是一种很好的实践。我最近想起了这个建议,但不记得理由是什么了。现在我听起来很奇怪。
是否有一个合理的理由总是包含默认语句? 这是语言依赖吗?我不记得当时我在用什么语言了——也许这适用于一些语言而不是其他语言?
在我的第一次代码评审中(不久前),有人告诉我,在所有switch语句中包含一个default子句是一种很好的实践。我最近想起了这个建议,但不记得理由是什么了。现在我听起来很奇怪。
是否有一个合理的理由总是包含默认语句? 这是语言依赖吗?我不记得当时我在用什么语言了——也许这适用于一些语言而不是其他语言?
当前回答
您应该有一个默认值来捕捉传入的非预期值。
然而,我不同意Adrian Smith关于默认的错误消息应该是完全没有意义的。可能会有一个你没有预见到的未处理的情况(这是一点),你的用户最终会看到,像“无法到达”这样的消息是完全没有意义的,在这种情况下对任何人都没有帮助。
举个例子,你有多少次经历过毫无意义的蓝皮书?或者致命异常@ 0x352FBB3C32342?
其他回答
我相信这是特定于语言的,对于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;
}
如果开关值(switch(variable))不能达到默认情况,则根本不需要默认情况。即使我们保留默认情况,它也不会被执行。这是死代码。
我会说这取决于语言,但在C中,如果你要打开一个枚举类型并处理每个可能的值,最好不要包含默认大小写。这样,如果您稍后添加了一个额外的enum标记,并且忘记将其添加到交换机中,称职的编译器将会就缺少的大小写向您发出警告。
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");
}