【问题标题】:Fall from one case to another using goto使用 goto 从一种情况转到另一种情况
【发布时间】:2017-04-19 13:40:48
【问题描述】:

我读过多篇文章说使用 goto 在编程中是一个巨大的禁忌。但有些人明确指出,滥用 goto 是错误的,并且在某些情况下,例如 switch 案例,这是预期用途。

所以我的问题是,供将来参考,这是最佳实践/更有效。

这个:

switch (a)
{
    case 1:
        //Something specific for case 1
        break;
    case 2:
        //Something specific to default and case 2
        break;
    default:
        //Something specific for default
        goto case 2;
}

或者这个:

switch (a)
{
    case 1:
        //Something specific for case 1
        break;
    case 2:
        //Something specific to default and case 2
        thatFunction();
        break;
    default:
        //Something specific for default
        thatFunction();
        break;
}

void thatFunction() { /*Case 2 stuff*/ }

编辑:这两个 switch 语句是示例,实际代码包含更多案例。

我工作场所的每个人要么从未使用过 goto,要么说他们只听说过从未使用过它。所以我来这里是为了一个明确的答案。我正在寻找一个答案和一个解释或一个链接。 谢谢,

【问题讨论】:

  • 我可能会考虑 goto 作为状态机。出于一个简单的原因,我会列出案例中的整个过程:可读性。这样你就不必记住你在 case 2 中的所有内容也会在 default case 中执行。
  • Use a 'goto' in a switch?的可能重复

标签: c# unity3d switch-statement goto


【解决方案1】:

您始终需要了解任何“否-否”(或“是-是”)背后的原因。这样您就可以了解应用规则在哪些地方有意义,在哪些地方没有意义。

goto 的大战一直追溯到没有真正的过程和函数的编程,甚至没有像循环这样简单的东西。 goto 让您可以从任何地方跳到其他任何地方,很难想象它的实际含义。 “不要使用 goto”是向结构化代码转变的一部分,而不是在代码周围进行大量跳转;使用 for (int i = 10; i > 0; i--) { ... } 之类的东西进行迭代,而不是 if (i-- > 0) goto startLoop;

switch 中,goto 受到约束——它只能做一件事,执行switch 语句的分支。事实上,在 C# 中,即使在 switch 语句之外,goto 也是非常受限制和安全的,并且很少具有在“Goto is evil”运动开始时所假设的任何含义。当然,这并不意味着你应该开始用gotos 替换所有循环:)

现在,如果事情变得如此复杂,那可能是 switch 首先不是解决您问题的好方法。也许您可以使用不同的结构来做您想做的事情 - 在 C# 中有很多方法可以实现多态性和/或代码重用,其中一种可能是一种更好的方法,可以让您使用更清晰的代码来做你想做什么。但我们真的不能帮助你:)

【讨论】:

  • 尽管 switch 语句中的安全性我仍然给goto 一个谨慎的外观。我更有可能找到替代方案,例如在嵌套循环中使用bool breakEarly 而不是使用goto breakOutOfInnerLoop。它感觉更安全,更具可读性。切换语句仅用于失败,因为我想要做的在另一种语言中工作的事情只能通过 goto 实现。
  • @Draco18s 这是风格问题。就我而言,bool breakEarly 只是出于宗教原因避免goto 的一种愚蠢方式,而且更难阅读:P 另一方面,我很高兴 switch 语句与 body 不要默认掉线。 C# 的设计理念是“让正确的事情变得容易,让错误的事情变得困难”,他们实际上设法实现了这一点……主要是。人们不会经常改变主意 - 你经常被“正常”的感觉所困扰。
  • 哦,当然,当然。只是说那是我喜欢的。
【解决方案2】:

答案是,循环往复的逻辑最好保留在宗教和政治上。你的default 真的是case 2,这意味着case 2 真的只是default。尽管case 2 中的某些执行可能在default 中没有发生,但在default 案例中您需要执行除if 条件之外的任何操作的情况极为罕见。此外,在排除故障时,如果您向后循环案例链,则无法立即确定您的 switch 评估结果。想象一下你的堆栈跟踪。

次使用goto,但这些通常在exceptional 情况下(看看我在那里做了什么)你需要立即执行一个操作(例如记录一些正在发生的事情)在break运行运行条件或无限循环之前在另一个线程上出错)。 goto 的一般规则与预处理器命令相同。如果有其他方法可以做同样有效的事情,您应该使用其他方法来实现逻辑连续性和可维护性。

【讨论】:

  • “您的‘默认’实际上是‘案例 2’,这意味着‘案例 2’实际上只是‘默认’” - 几乎没有,考虑到以下情况case2代码在跳转到default之前做了额外的代码
  • 本文之前的示例中没有。不过,这在紧接着的句子中得到了解决。
猜你喜欢
  • 2013-05-13
  • 2011-11-21
  • 2017-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-25
相关资源
最近更新 更多