带返回的switch语句 - 代码正确性

问题描述 投票:76回答:17

假设我在C中有大约这个结构的代码:

switch (something)
{
    case 0:
      return "blah";
      break;

    case 1:
    case 4:
      return "foo";
      break;

    case 2:
    case 3:
      return "bar";
      break;

    default:
      return "foobar";
      break;
}

现在很明显,代码正常运行不需要“break”,但如果我不把它们放在我身上,它看起来就像是不好的做法。

你怎么看?删除它们可以吗?或者你会保持他们增加“正确性”?

c switch-statement correctness
17个回答
114
投票

删除break语句。它们不是必需的,也许一些编译器会发出“无法访问的代码”警告。


2
投票

对于“正确性”,单入口,单出口块是个好主意。至少他们是我获得计算机科学学位的时候。所以我可能会声明一个变量,在开关中分配它并在函数结束时返回一次


2
投票

你怎么看?删除它们可以吗?或者你会保持他们增加“正确性”?

删除它们很好。使用return正是不应该使用break的情况。


1
投票

有趣。大多数这些答案的共识似乎是多余的break声明是不必要的混乱。另一方面,我在一个开关中读取break语句作为案例的“结束”。 case挡不到break倾向于跳出来,因为潜在的下降虽然错误。

我知道当有一个return而不是break时,情况并非如此,但这就是我的眼睛如何看到'案件在一个开关中阻塞,所以我个人更希望每个casebreak配对。但是,在break多余/无法到达之后,许多编译器都抱怨return,显然我似乎仍然是少数。

因此,在break之后摆脱return

注意:所有这些都忽略了违反单一进入/退出规则是否是个好主意。就这一点而言,我有一个意见,不幸的是根据情况而变化......


0
投票

我说删除它们。如果您的代码是如此难以理解,以至于您需要在安全方面坚持中断,那么您应该重新考虑您的编码风格:)

此外,我总是希望不要在switch语句中混合break和return,而是坚持使用其中一个。


0
投票

我个人倾向于失去breaks。这个习惯的一个来源可能来自Windows应用程序的编程窗口过程:

LRESULT WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    switch (uMsg)
    {
        case WM_SIZE:
            return sizeHandler (...);
        case WM_DESTROY:
            return destroyHandler (...);
        ...
    }

    return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

我个人认为这种方法比声明每个处理程序设置的返回变量更简单,简洁和灵活,然后在最后返回它。鉴于这种方法,breaks是多余的,因此应该 - 它们没有任何用处(语法上或IMO可视)并且只会膨胀代码。


0
投票

我认为* break * s是有目的的。这是为了让编程的“意识形态”保持活力。如果我们只是在没有逻辑连贯性的情况下“编程”我们的代码,也许它现在可以读取,但明天再尝试。试着向老板解释一下。尝试在Windows 3030上运行它。

漂白剂,这个想法很简单:


Switch ( Algorithm )
{

 case 1:
 {
   Call_911;
   Jump;
 }**break**;
 case 2:
 {
   Call Samantha_28;
   Forget;
 }**break**;
 case 3:
 {
   Call it_a_day;
 }**break**;

Return thinkAboutIt?1:return 0;

void Samantha_28(int oBed)
{
   LONG way_from_right;
   SHORT Forget_is_my_job;
   LONG JMP_is_for_assembly;
   LONG assembly_I_work_for_cops;

   BOOL allOfTheAbove;

   int Elligence_says_anyways_thinkAboutIt_**break**_if_we_code_like_this_we_d_be_monkeys;

}
// Sometimes Programming is supposed to convey the meaning and the essence of the task at hand. It is // there to serve a purpose and to keep it alive. While you are not looking, your program is doing  // its thing. Do you trust it?
// This is how you can...
// ----------
// **Break**; Please, take a **Break**;

/ *只是一个小问题。在阅读上述内容时你喝了多少咖啡?它。有时打破系统* /


0
投票

一次退出代码。这为代码提供了更好的可读性。在两者之间添加返回语句(多个退出)将使调试变得困难。


0
投票

如果您有“查找”类型的代码,则可以将switch-case子句自行打包在方法中。

我在一个“爱好”系统中有一些我正在开发的乐趣:

private int basePerCapitaIncomeRaw(int tl) {
    switch (tl) {
        case 0:     return 7500;
        case 1:     return 7800;
        case 2:     return 8100;
        case 3:     return 8400;
        case 4:     return 9600;
        case 5:     return 13000;
        case 6:     return 19000;
        case 7:     return 25000;
        case 8:     return 31000;
        case 9:     return 43000;
        case 10:    return 67000;
        case 11:    return 97000;
        default:    return 130000;
    }
}

(是的。那是GURPS空间...)

我同意其他人的意见,在大多数情况下,你应该避免在一个方法中多次返回,我确实认识到这个可能更好地实现为数组或其他东西。我刚刚发现switch-case-return非常容易匹配一个查找表,输入和输出之间有1-1相关性,就像上面那样(角色扮演游戏充满了它们,我相信它们存在于其他“企业”):D

另一方面,如果case子句更复杂,或者在switch语句之后发生了某些事情,我不建议在其中使用return,而是在switch中设置一个变量,以break结束它,然后返回最后变量的值。

(在...第三手?你可以随时重构一个切换到自己的方法......我怀疑它会对性能产生影响,如果现代编译器甚至可以将其识别为可以内联的东西...)


27
投票

我会完全采取不同的方法。不要在方法/功能的中间返回。相反,只需将返回值放在局部变量中并在结尾处发送它。

就个人而言,我发现以下内容更具可读性:

String result = "";

switch (something) {
case 0:
  result = "blah";
  break;
case 1:
  result = "foo";
  break;
}

return result;

8
投票

我个人会删除退货并保持休息。我会使用switch语句为变量赋值。然后在switch语句后返回该变量。

虽然这是一个有争议的观点,但我一直认为良好的设计和封装意味着一种方式和一种方式。保证逻辑更容易,并且您不会因为函数的圈复杂度而意外错过清理代码。

一个例外:如果在函数开头检测到错误参数(在获取任何资源之前),则提前返回是可以的。


5
投票

保持休息时间 - 如果/如果休息时间已经到位,您在以后编辑代码时不太可能遇到麻烦。

话虽如此,许多人(包括我)认为从功能中间返回是不好的做法。理想情况下,函数应该有一个入口点和一个出口点。


5
投票

删除它们。从case语句返回它是惯用的,否则它是“无法访问的代码”噪音。


5
投票

我会删除它们。在我的书中,像这样的死代码应该被视为错误,因为它会让你做一个双重考虑并问自己“我怎么能执行那条线?”


4
投票

我通常会在没有它们的情况下编写代码。国际海事组织,死代码往往表明邋and和/或缺乏理解。

当然,我也会考虑这样的事情:

char const *rets[] = {"blah", "foo", "bar"};

return rets[something];

编辑:即使使用编辑的帖子,这个一般的想法可以正常工作:

char const *rets[] = { "blah", "foo", "bar", "bar", "foo"};

if ((unsigned)something < 5)
    return rets[something]
return "foobar";

在某些时候,特别是如果输入值是稀疏的(例如,1,100,1000和10000),则需要稀疏数组。你可以很好地将它实现为树或地图(当然,在这种情况下,交换机仍然可以工作)。


2
投票

我会说删除它们并定义一个默认值:branch。


2
投票

有一个阵列不是更好

arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"

并做return arr[something];

如果这是关于一般的做法,你应该在交换机中保留break语句。如果您将来不需要return语句,它会降低它下降到下一个case的可能性。

© www.soinside.com 2019 - 2024. All rights reserved.