代码之家  ›  专栏  ›  技术社区  ›  houbysoft

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

  •  75
  • houbysoft  · 技术社区  · 15 年前

    假设我有一个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”不是代码正确运行所必需的,但是如果我不把它们放在这里,这看起来有点不好。

    你怎么认为?可以移除它们吗?还是为了提高“正确性”而保留它们?

    17 回复  |  直到 7 年前
        1
  •  110
  •   kgiannakakis    15 年前

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

        2
  •  27
  •   ChrisLively    11 年前

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

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

    String result = "";
    
    switch (something) {
    case 0:
      result = "blah";
      break;
    case 1:
      result = "foo";
      break;
    }
    
    return result;
    
        3
  •  8
  •   Amardeep AC9MF    15 年前

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

    尽管这是一个有争议的观点,但我一直认为良好的设计和封装意味着一种方式进入和一种方式退出。这样更容易保证逻辑,并且不会因为函数的循环复杂性而意外错过清理代码。

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

        4
  •  5
  •   Paul R    15 年前

    保留中断-如果/当您稍后编辑代码时,如果中断已经就位,则不太可能遇到问题。

    尽管如此,许多人(包括我)认为从函数中间返回是一种糟糕的实践。理想情况下,一个函数应该有一个入口点和一个出口点。

        5
  •  5
  •   Stephen    15 年前

    除去它们。从那里回来是惯用的 case 语句,否则就是“无法访问的代码”噪声。

        6
  •  4
  •   Hank Gay    15 年前

    我会把它们移走。在我的书中,这样的死代码应该被认为是错误的,因为它使您做了一个二次尝试,并问自己“我将如何执行该行?”

        7
  •  4
  •   Jerry Coffin    15 年前

    我通常不写代码。在我看来,死代码往往意味着马虎和/或缺乏理解。

    当然,我也会考虑:

    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),您需要一个稀疏数组。您可以很好地将其作为树或映射来实现(当然,在这种情况下,开关仍然有效)。

        8
  •  2
  •   Bella    15 年前

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

        9
  •  2
  •   Vivin Paliath    15 年前

    用一个数组

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

    并且做 return arr[something]; ?

    如果是一般的练习,你应该保持 break 开关中的语句。如果你不需要 return 在未来的声明中,它减少了它落入下一个的机会 case .

        10
  •  2
  •   Steve Sheldon    15 年前

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

        11
  •  2
  •   OscarRyz    15 年前

    你怎么认为?可以移除它们吗?还是为了提高“正确性”而保留它们?

    把它们移走就好了。使用 return 确切地 在什么情况下 break 不应使用。

        12
  •  1
  •   Michael Burr    15 年前

    有趣。大多数这些答案的共识似乎是 break 陈述是不必要的混乱。另一方面,我读到 打破 开关中的语句,作为案例的“结束”。 case 不以A结尾的块 打破 虽然有虫子,但还是有可能掉下来。

    我知道当有一个 return 而不是 打破 但我的眼睛就是这样“读出”开关中的情况,所以我个人更喜欢每一个 案例 与…搭配 打破 . 但许多编译器确实抱怨 打破 后一 返回 是多余的/无法达到的,显然我似乎是少数。

    所以摆脱 打破 紧随其后 返回 .

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

        13
  •  0
  •   Thomas Kjørnes    15 年前

    我说把它们移走。如果您的代码是如此不可读,以至于您需要在“安全的一面”中插入中断符,那么您应该重新考虑您的编码风格:)

    另外,我一直不喜欢在switch语句中混合使用break和return,而是坚持使用其中的一个。

        14
  •  0
  •   Sheng Jiang 蒋晟    12 年前

    我个人倾向于失去 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);
    }
    

    我个人认为这种方法比声明由每个处理程序设置的返回变量,然后在最后返回它要简单、简洁和灵活得多。考虑到这种方法, 打破 S是多余的,因此应该去——它们没有任何有用的用途(语法上或视觉上),只会膨胀代码。

        15
  •  0
  •   Cruentos Solum    12 年前

    我认为 *断裂 *是有目的的。它是为了保持编程的“意识形态”。如果我们只是“编程”我们的代码,而没有逻辑一致性,也许现在它对您来说是可读的,但是明天再试一次。试着向你的老板解释。尝试在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**;
    

    /*不过只是个小问题。阅读上述内容时,你喝了多少咖啡?I.T. 打破 系统有时*/

        16
  •  0
  •   antish    7 年前

    一点退出代码。这提供了更好的代码可读性。在中间添加RETURN语句(多个出口)将使调试困难。

        17
  •  0
  •   Erk    7 年前

    如果您有“lookup”类型的代码,那么可以将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返回是一个很容易匹配的查找表,输入和输出之间有1-1的相关性,就像上面所说的那样(角色扮演游戏充满了它们,我确信它们也存在于其他“企业”中):d

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

    (关于……第三?手…您总是可以将开关重构为它自己的方法…我怀疑它会对性能产生影响,如果现代编译器甚至能够将其识别为可以内联的东西,我也不会感到惊讶…)

    推荐文章