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

时间:2010-06-17 20:36:12

标签: c switch-statement correctness

假设我在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;
}

现在很明显,“破解”并不是代码正常运行所必需的,但如果我不把它们放在那里,它看起来就像是不好的做法。

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

18 个答案:

答案 0 :(得分:113)

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

答案 1 :(得分:27)

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

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

String result = "";

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

return result;

答案 2 :(得分:8)

就个人而言,我会删除退货并保留休息时间。我会使用switch语句为变量赋值。然后在switch语句后返回该变量。

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

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

答案 3 :(得分:5)

删除它们。从case语句返回是不恰当的,否则就是“无法访问的代码”。

答案 4 :(得分:5)

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

答案 5 :(得分:5)

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

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

答案 6 :(得分: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),则需要使用稀疏数组。你可以很好地将它实现为树或地图(当然,在这种情况下,交换机仍可以工作)。

答案 7 :(得分:2)

我想说删除它们并定义默认值:branch。

答案 8 :(得分:2)

拥有

的数组不是更好
arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"

并做return arr[something];

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

答案 9 :(得分:2)

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

答案 10 :(得分:2)

  

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

删除它们很好。使用return 完全不应使用break的方案。

答案 11 :(得分:1)

我认为将所有内容都放在一个数组中,然后获取键和值会更容易。

类似的东西:

$arr_some = [
    '0' => 'blah',
    '4' => 'foo',
    '3' => 'bar'
];

if ( !isset($arr_some[$something]) ) {
    return 'foobar';
}

return $arr_some[$something];

答案 12 :(得分:1)

有趣。大多数这些答案的共识似乎是多余的break陈述是不必要的混乱。另一方面,我将开关中的break语句读作案例的“结束”。 casebreak结尾的return块往往会跳出来,因为潜在的漏洞可能会出现问题。

我知道当break代替case时,情况并非如此,但这就是我的眼睛如何“读取”开关中的情况阻塞,所以我个人更希望每个breakbreak配对。但是很多编译器在return多余/无法访问之后会抱怨break,显然我似乎仍然是少数。

所以摆脱return之后的{{1}}。

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

答案 13 :(得分:0)

我个人倾向于失去break。这个习惯的一个来源可能来自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);
}

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

答案 14 :(得分:0)

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

Bleah,这个想法非常简单:


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

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

答案 15 :(得分:0)

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

答案 16 :(得分:0)

如果你有&#34;查找&#34;代码类型,您可以将switch-case子句单独打包在方法中。

我有一些&#34;爱好&#34;系统我为了好玩而开发:

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相关性,就像上面那样(角色扮演游戏充满了它们,我相信它们存在于其他&#34;业务&#34;以及:D

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

(在......第三方面......你总是可以将一个开关重构为自己的方法......我怀疑它会对性能产生影响,如果现代编译器不会让我感到惊讶甚至可以认为它是可以内联的东西...)

答案 17 :(得分:0)

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

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