如何在Objective-C的switch语句中使用goto?

6

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

我的代码大致如下:(有很多代码,我只是把它全部省略了)

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

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

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

default:
break;

感谢您的时间! -Jeff


9
不要这样做,那会是很糟糕的编程实践。 - zaph
你是否正在寻找一种方法,如果一个值或另一个值满足条件时,可以运行相同的代码块?如果是这样,你可以直接跳转到正确的代码块。 - user152759
请把多余的大括号删除掉: - KevinDTimm
4个回答

17

通常情况下,无条件跳转的做法是非常糟糕的惯例。

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

如果你真的想这样做,可以使用goto来实现类似以下代码:

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

注意:我上面只提供了代码示例以回答你的问题。现在我感觉很糟糕,可能需要购买一些恶劣代码抵消


1
所以这个方法肯定超级庞大!将case语句中的代码删除并将其放入其他方法中可能会使阅读更容易。而且,如果您有固定数量的按钮,可以使用目标-操作直接将每个按钮与其自己的方法相关联。 - Ben S
我以前的做法是为每个情况编写一个单独的方法,在IB中,所有按钮都连接到“IBAction”,但我的老板认为,如果我使用Switch语句而不是单独的方法,代码将会“更可靠、优雅和运行更快”。所以你的意思是最好再次使用单独的方法吗?此外,我之前听说过“goto”不好用...你知道它为什么不好用吗? - Jeff
除非您遇到性能问题并且分析应用程序后发现这是原因,否则您甚至不应该考虑优化此类内容。即使可以节省纳秒级别的时间(我怀疑是否真的更快),也无法抵消将投入其中的维护时间。 - Ben S
1
与其将其拆分为单独的方法,然后逐个连接,最好的方法可能是保留您拥有的方法(因此只有一个要连接的点),但正如其他人建议的那样,将所有公共代码放入一个方法中,您可以从switch语句中调用该方法。 - Kendall Helmstetter Gelner
我同意Kendall的观点。switch语句可能没问题,但是要将所有共同部分拆分成函数。至于为什么goto被认为是有害的,这归结于可读性和潜在的过度/误用。goto使代码更难理解,因为你必须跳来跳去,当查看一行代码时,你不知道如何到达那里... [总的来说,“永远不要使用goto语句。永远不要”是那些你绝不能打破的规则;除非你理解为什么它是一个规则,并且可以安全地打破它。] - Brian Postow
显示剩余2条评论

4

不要使用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的实际原因是你必须在switch-case树中搜索goto标签。

如果你的switch逻辑改变了,你将面临一种混乱的局面。

如果你将公共代码拆分成自己的方法,代码更容易阅读、调试和扩展。


0

你应该尝试重写你的代码,比如使用递归调用或者将常见的部分提取出来并调用一个单独的函数。但是作为对你问题的快速修复和答案,你可以在 switch 语句之前放置一个标签,并使用 goto 命令跳转到它,像这样:

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

它会循环,直到视图编号不再改变。但这仍然基本上只是一个漂亮的 goto。

既然我们正在使用goto,您可以跳转到另一个case,就像已经指出的那样。您还可以执行类似于Duff设备的花哨操作,将case放入其他块中。但那只是疯狂的.. :)


-1

我将这个答案设为社区 wiki,因为它实际上并没有直接回答问题。

正如其他人所说,这是非常糟糕的风格,会导致代码难以阅读...

替代方案:

  1. 将公共代码分解成一个单独的函数,并在两个位置调用该函数。
  2. 使用 fallthroughs,在 case 上省略 break,它会自动转到下一个 case(记住,case 不必按数字顺序排列!)
  3. 如果你只想在另一个 case 中执行部分 case,请使用 if 进行保护:

例如:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接