【问题标题】:How can I use goto in a switch statement in Objective-C?如何在 Objective-C 的 switch 语句中使用 goto?
【发布时间】:2009-11-19 15:59:16
【问题描述】:

在我的代码中,我需要能够在同一个 switch 语句中跳转(转到)不同的情况。有没有办法做到这一点?

我的代码是这样的:(有很多代码我都省略了)

switch (viewNumber) {
case 500:
        // [...]
break;

case 501:
        // [...]
break;
.
.
.
.
.

case 510:
        // [...]
break;

default:
break;

}

感谢您的宝贵时间! -杰夫

【问题讨论】:

  • 不要,那将是非常糟糕的编码习惯。
  • 您是否正在寻找一个值是否命中,它们都运行相同的代码案例?如果是这样,您可以找到正确的案例。
  • 请去掉所有多余的大括号:(

标签: iphone objective-c switch-statement goto


【解决方案1】:

按照您的要求无条件跳跃通常是非常糟糕的做法。

我认为更具可读性/可维护性的解决方案是将共享代码放在一个方法中,并让多个案例调用该方法。

如果您真的想要,您可以使用goto 执行以下操作:

switch(viewNumber) {
    case 500:
        // [...]
        goto jumpLabel;
    case 501:
        // [...]
        break;
    case 502:
        // [...]
        jumpLabel:
        // Code that 500 also will execute
        break;
    default:break;
}

注意:我只提供了上面的代码示例来回答您的问题。我现在觉得很脏,我可能不得不买一些Bad Code Offsets。

【讨论】:

  • 谢谢。 switch 语句在一个方法中: - (IBAction) showViewAction:(id) sender { viewNumber = [sender tag];但是我使用的案例#是来自发件人的标签 ID。因此,当用户点击标签 ID 为 500 的按钮时,该方法会使用该标签来了解要使用的大小写。
  • 所以这个方法一定很厉害!从case 语句中删除代码并将它们放在其他方法中可能会使事情更容易阅读。此外,如果您有固定数量的按钮,您可以使用 target-action 将每个按钮直接关联到自己的方法。
  • 我过去的方式是针对每种情况使用单独的方法,并且在 IB 中,所有按钮都连接到“IBAction”,但我的老板认为代码会“更多可靠、优雅且运行速度更快”,如果我使用 Switch 语句而不是单独的方法。所以你说再次使用单独的方法会更好吗?我也听说过“goto”不好用……你知道为什么不好吗?
  • 在 SO (stackoverflow.com/search?q=goto+bad) 上讨论 goto 的问题有很多。我认为这个开关less 优雅得多,特别是如果某些按钮没有任何关联。阅读起来要困难得多,因为在一个地方有很多不相关的代码,并且每次按下按钮时,您都需要进行大量比较以找到正确的案例块。 IMO,让按钮简单地调用它需要的代码比必须通过这样的开关“过滤器”要好得多。
  • 与其将其分解为单独连接的单独方法,最好的方法很可能是保留您拥有的方法(因此只需连接一个点),但正如其他人所建议的那样,将所有通用代码并将其放入您从 switch 语句调用的方法中。
【解决方案2】:

不要使用goto,而是重构您的代码,以便使用公共代码的两个(或多个)案例改为在一个公共方法中调用它。

类似:

switch (value) {
   case (firstValue):
       // ...
       break;
   case (secondValue):
       [self doSharedCodeForSecondAndThirdValues];
       break;
   case (thirdValue):
       [self doSharedCodeForSecondAndThirdValues];
       break;
   default:
       break;
}

// ...

- (void) doSharedCodeForSecondAndThirdValues {
   // do stuff here that is common to second and third value cases
}

使用goto 并不是世界末日,尽管这是一种不好的做法。

避免使用goto 的实际原因是您必须搜索swtich-case 树才能找到goto 标签。

如果你的开关逻辑发生变化,你手上的情况就会很混乱。

如果将通用代码提取到自己的方法中,代码更易于阅读、调试和扩展。

【讨论】:

    【解决方案3】:

    您可能应该尝试重写您的代码,例如递归调用,或者只是分解常见的东西并调用一个单独的函数。但作为对您问题的修复和快速回答,您可以在切换之前放置一个标签并转到它,就像这样

    switchLabel:
    switch(viewNumber) {
      case 500: {
        viewNumber = 501;
        goto switchLabel;
      }
    }
    

    不确定这里的 Objective-C 语法,但您也可以尝试其变体

    int lastView = 0;
    
    while (lastView != viewNumber)
      switch(lastView = viewNumber) {
        case 500: {
          viewNumber = 501;
          break;
        }
      }
    

    它将继续循环,直到 viewNumber 不再改变。不过,这仍然只是一个漂亮的 goto。

    而且由于我们正在执行 goto,您可以转到另一个案例,正如已经指出的那样。您还可以通过将箱子放在其他块内来做类似于 Duff 设备的花哨的东西。但这只是疯了.. :)

    【讨论】:

      【解决方案4】:

      [我正在制作这个答案社区维基,因为它本身并没有真正回答问题]

      正如其他人所说,这是一种非常糟糕的风格,并且会导致无法阅读的代码......

      替代方案:

      1. 将通用代码分解为一个单独的函数,并在 2 个地方调用它。
      2. 使用fallthroughs,去掉一个case的中断,它会一直到下一个(记住,case不必按数字顺序!)
      3. 如果您只想在另一个案例中完成部分案例,请使用 if 保护它:

      如

      case 500:
       .
       .
       .
      case 501:
          if(viewNumber == 501)    {
           .
           .
           .
          }
           .
           .
           .
          break;
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-23
        • 2015-11-07
        相关资源
        最近更新 更多