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

Switch语句出错…是否允许?[闭门]

  •  93
  • Fostah  · 技术社区  · 17 年前

    这是编程语言不应该明确允许的(像C#一样,尽管它提供了一个解决方法),还是任何强大到足以让程序员掌握的语言的一个特性?

        switch(m_loadAnimSubCt){
            case 0:
            case 1:
                // Do something
                break;
            case 2:
            case 3:
            case 4:
                // Do something
                break;
       }
    

    然而,我担心这样的事情。

       switch(m_loadAnimSubCt){
            case 0:
            case 1:
                // Do something, but fall through to the other cases
                // after doing it.
    
            case 2:
            case 3:
            case 4:
                // Do something else.
                break;
       }
    

    这样,每当case为0,1时,它将执行switch语句中的所有操作。我已经看到了这一点,我只是不知道我是否同意switch语句应该这样使用。我认为第一个代码示例非常有用和安全。第二种似乎有点危险。

    12 回复  |  直到 5 年前
        1
  •  105
  •   Fred Larson    9 年前

    这可能取决于你考虑的问题。我同意这类事情:

    switch (value)
    {
      case 0:
        result = ZERO_DIGIT;
        break;
    
      case 1:
      case 3:
      case 5:
      case 7:
      case 9:
         result = ODD_DIGIT;
         break;
    
      case 2:
      case 4:
      case 6:
      case 8:
         result = EVEN_DIGIT;
         break;
    }
    

    但是如果你有一个案例标签,接着是另一个案例标签的代码,我几乎总是认为那是邪恶的。也许将公共代码移动到函数中,并从两个位置调用会是一个更好的主意。

    请注意,我使用 C++ FAQ "evil"

        2
  •  60
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    这是一把双刃剑。它有时非常有用,但往往很危险。

    什么时候好?当你想要10个案件都以同样的方式处理。。。

    switch (c) {
      case 1:
      case 2:
                ... Do some of the work ...
                /* FALLTHROUGH */
      case 17:
                ... Do something ...
                break;
      case 5:
      case 43:
                ... Do something else ...
                break;
    }
    

    我喜欢的一条规则是,如果你做了任何不包括休息的事情,你需要一条清晰的注释/*错误提示*/来表明这是你的意图。

        3
  •  24
  •   tzot    17 年前

    你听说过吗 Duff's device ? 这是使用switch fallthrough的一个很好的例子。

        4
  •  21
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    失败是一件非常方便的事情,这取决于你在做什么。考虑一下这样一种简洁易懂的方式来安排选项:

    switch ($someoption) {
      case 'a':
      case 'b':
      case 'c':
        // Do something
        break;
    
      case 'd':
      case 'e':
        // Do something else
        break;
    }
    

    想象一下用if/else这样做。那将是一片混乱。

        5
  •  10
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    它可以非常有用几次,但一般来说,没有失败是理想的行为。应该允许失败,但不能含蓄。

    例如,要更新某些数据的旧版本,请执行以下操作:

    switch (version) {
        case 1:
            // Update some stuff
        case 2:
            // Update more stuff
        case 3:
            // Update even more stuff
        case 4:
            // And so on
    }
    
        6
  •  6
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    switch(myParam)
    {
      case 0 or 1 or 2:
        // Do something;
        break;
      case 3 or 4:
        // Do something else;
        break;
    }
    

    注意:如果您使用标志声明枚举中的所有案例,那么这在枚举中已经是可能的,对吗?听起来也没那么糟糕;这些案例很可能(应该?)已经成为您的enum的一部分了。

    对于使用扩展方法的流畅接口来说,这可能是一个很好的例子(没有双关语)?比如,呃。。。

    int value = 10;
    value.Switch()
      .Case(() => { /* Do something; */ }, new {0, 1, 2})
      .Case(() => { /* Do something else */ } new {3, 4})
      .Default(() => { /* Do the default case; */ });
    

    虽然这可能更难理解:P

        7
  •  4
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    与任何东西一样:如果小心使用,它可能是一个优雅的工具。

    然而,我认为这些缺点不仅仅是合理的 使用它,最后不再允许它(C#)。这些问题包括:

    • 很容易“忘记”休息
    • 对于代码维护人员来说,这并不总是显而易见的 那个 遗漏的中断是故意的

    switch (x)
    {
    case 1:
    case 2:
    case 3:
     Do something
     break;
    }
    

    使用开关/机箱直通:

    switch (x)
    {
    case 1:
        Some code
    case 2:
        Some more code
    case 3:
        Even more code
        break;
    }
    

    令人不快的 例如,除非您正在维护使用这种样式并得到充分理解的遗留代码。

        8
  •  4
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    无论我在哪里使用它,我都会确保它得到了正确的评论:

    switch($var) {
        case 'first':
            // Fall-through
        case 'second':
            i++;
            break;
     }
    
        9
  •  3
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    除非 他们认为值得努力的是,给它写一个注释块,它描述了这是一个故意的失败,以及为什么这个解决方案比其他方案更好。这不鼓励草率的使用,但在使用它有优势的情况下仍然允许草率的使用。

    这或多或少相当于我们在太空项目中所做的,当有人想要违反编码标准时:他们必须申请豁免(我被要求就裁决提出建议)。

        10
  •  2
  •   Matt Dillard    17 年前

    我不喜欢我的工作 switch 语句容易出错,很难阅读。唯一的例外是当多个 case 所有的语句都可以 同样的事情。

        11
  •  1
  •   warren    17 年前

    在某些情况下,使用跳转是程序员的一种懒惰行为——例如,他们可以使用一系列| |语句,但可以使用一系列“全面覆盖”切换情况。

    话虽如此,当我知道这一点时,我发现他们特别有用 我仍然需要这些选项(例如在菜单响应中),但尚未实现所有选项。类似地,如果您同时对“a”和“a”进行遍历,我发现使用开关遍历比使用复合if语句要干净得多。

    这可能是风格和程序员的想法的问题,但我通常不喜欢以“安全”的名义删除语言的组件——这就是为什么我更倾向于C及其变体/后代,而不是Java。我喜欢在没有“理由”的情况下拿着指针之类的东西胡闹。

        12
  •  1
  •   Peter Mortensen Pieter Jan Bonestroo    6 年前

    只有当它被用作跳转到代码块中的跳转表时,才应该使用Fall-through。如果代码中有任何部分在更多案例之前无条件中断,则所有案例组都应以这种方式结束。