【问题标题】:Use a 'goto' in a switch?在开关中使用“goto”?
【发布时间】:2011-01-21 06:37:41
【问题描述】:

我看到了一个建议的编码标准,内容为Never use goto unless in a switch statement fall-through

我不关注。这个“例外”案例究竟是什么样的,证明goto是合理的?

【问题讨论】:

  • 我不会在 switch 语句中使用它。
  • 阅读前三个字然后goto end
  • 我自己不使用它的唯一原因是因为其他人一提到它就会不高兴。我很快就对过度敏感的人感到厌烦(我猜来自工程师)。
  • @The Smartest:switch 语句本身已经可以有很多 goto ,但它们的命名不同:每个 break 都是一个 goto .
  • @chiccodoro 这没什么,实际上每个case 都是labelswitch 本质上是goto。每个break 是一个goto,但每个continue 也是一个goto。

标签: c# coding-style switch-statement goto


【解决方案1】:

这个构造在 C# 中是非法的:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
   case 1:
       Console.WriteLine("variable is >= 1");
}

在 C++ 中,如果variable = 2,它将运行两行。这可能是故意的,但在第一个案例标签的末尾很容易忘记break;。出于这个原因,他们在 C# 中将其设为非法。要模仿跌倒行为,您必须明确使用goto 来表达您的意图:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
       goto case 1;
   case 1:
       Console.WriteLine("variable is >= 1");
       break;
}

也就是说,有a few cases,其中goto实际上是解决问题的好方法。 Never shut down your brain 带有“从不使用某些东西”的规则。如果它是 100% 无用的,那么它一开始就不会存在于语言中。不要使用goto 是一个指南;这不是法律。

【讨论】:

  • @Mehrdad:我很想读“永远不要关闭你的大脑”,但我觉得我有点晚了.. 似乎它已被删除。如果您偶然有任何其他参考链接,是否可以刷新链接?谢谢
  • @curiousBoy 不幸的是,我不记得 3 年多后是什么,而且我没有足够的代表访问程序员.stackexchange 来查看它(我怀疑它曾经是 Stack Overflow 的帖子我链接到)。
  • 不幸的是,即使在最初发布 5 年后它仍然具有相关性
  • “永远不要关闭你的大脑”的链接不见了。我希望 SO 允许某些自以为是的问题和答案,因为它使生活变得有趣。这是一个类似的问题stackoverflow.com/questions/406760/…
  • 唯一的“最佳实践”youShouldBeUsingAllTheTime 是“使用你的大脑”。太多的人加入太多的潮流,并试图将方法、模式、框架等强加到不值得他们这么做的事情上。仅仅因为某些东西是新的,或者因为受人尊敬的人有意见,并不意味着它适合所有人:) 编辑:澄清一下——我认为人们不应该忽视最佳实践、有价值的意见等。只是人们不应该只是盲目地跳上某事而不考虑为什么这个“东西”如此出色,它是否适用于我正在做的事情,它带来了什么好处/缺点?
【解决方案2】:

C# 拒绝让案例隐含地失败(除非案例中没有代码),就像在 C++ 中一样:您需要包含break。要明确失败(或跳转到任何其他情况),您可以使用goto case。由于没有其他方法可以获得这种行为,因此大多数(合理的)编码标准都会允许它。

switch(variable)
{
case 1:
case 2:
    // do something for 1 and 2
    goto case 3;
case 3:
case 4:
    // do something for 1, 2, 3 and 4
    break;
}

一个现实的例子(根据要求):

switch(typeOfPathName)
{
case "relative":
    pathName = Path.Combine(currentPath, pathName);
    goto case "absolute";

case "expand":
    pathName = Environment.ExpandEnvironmentVariables(pathName);
    goto case "absolute";

case "absolute":
    using (var file = new FileStream(pathName))
    { ... }
    break;

case "registry":
    ...
    break;
}

【讨论】:

  • 这句话就是这个意思,但问题是why is this justified?
  • 问题是“这个‘异常’案例究竟会是什么样子”。 C# 中没有其他选择的事实证明了这一点。
  • 异常情况是什么样的,而不是实现。即in what circumstance would you want to do this.
  • “此异常情况”是指“在 switch-statement fallthrough 中”,使用“除非”一词表示对在主题之前指定的“从不使用”的一般规则的例外, “去。” (如果我走得太快,请阻止我。)
【解决方案3】:
   public enum ExitAction {
        Cancel,
        LogAndExit,
        Exit
    }

这样更整洁

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        goto case ExitAction.Exit;
    case ExitAction.Exit:
        Quit();
        break;
}

比这个(特别是如果你在 Quit() 中做更多的工作)

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        Quit();
        break;
    case ExitAction.Exit:
        Quit();
        break;
}

【讨论】:

  • 你不能 goto case 枚举 - 它必须是一个常数。真的很遗憾,因为它会很方便,但这似乎是行为。
  • err,是的,你可以,枚举被视为常量
  • 呸,我之前测试时一定是打错了。它现在编译...我发誓以前没有。对不起。 +1
【解决方案4】:

除了使用goto case,你还可以goto在另一个case子句中的标签:

    switch(i) {
    case "0":
        // do some stuff
        break;
    case "1":
        // other stuff, then "fall through" to next case clause
        goto Case2;
    case "2":
    Case2:
        break;
    }

这样,您可以跳转到另一个 case 子句,而不必担心表达式的值或类型。

某种可以替代break 的显式“失败”关键字会很好,不过...

【讨论】:

  • 我才意识到这是一岁;对于那个很抱歉!我还停留在 2011 年。
  • 这可能是死灵术,但它是好的死灵术类型。它实际上帮助了我。 :) +1 了
  • 你也可以使用:goto case "2";
【解决方案5】:

这是 C# 允许 switch case 'fallthrough' 的唯一方式。在 C# 中(与 C、C++ 或 Java 不同),switch 语句中的 case 块必须以 break 或其他一些显式跳转语句结尾。

【讨论】:

    【解决方案6】:

    作为对上述 Mehrdad Afshari 建议的扩展,我绝不会主张简单地将结构视为“糟糕的代码”或“糟糕的编码实践”。即使是“goto”语句在宏伟的计划中也占有一席之地。他们是邪恶的教条并没有因为构造中的任何固有缺陷而成为过去 - 这是因为他们被严重(和糟糕地)过度使用。

    在任何情况下,Kernighan 和 Ritchie 都认为让案件落空才是正确的做法。坦率地说,我更倾向于相信他们的推理,而不是在整个华盛顿州雷德蒙德的任何人的脑海中可以想象的任何事情。或者任何基于雷德蒙德任何人的智慧的教条。

    如果您听到“从不使用 xxx”,请在脑海中附加“无故”。只是教条地扔掉任何东西是荒谬的。设备的存在是因为制造它们是有原因的。事后看来,它们通常被称为“坏”,不是因为设备本身有任何故障,而是因为不完全理解它们的人使用不当。因此,该设备几乎不会“坏”。几乎总是不好的是用户理解。即使是原子裂变和聚变也是如此。

    我见过极其怪诞的代码结构,其唯一功能是避免使用“goto”语句。更糟糕的是什么? “goto [label]”,还是30行恶心的代码,其作用是避免输入“goto [label]”?

    在教条之前寻求知识。三思而后行。这些都是有用的建议。

    【讨论】:

    • 正确的观点。有趣的是,这几乎适用于所有事情,而不仅仅是设备。例如一把枪,它不是桌子上的武器造成任何伤害,而是使用它的人。它也可以用于保护被抢劫的人等好事。这完全取决于用户。
    【解决方案7】:

    我知道这是老话题,但问题仍然是实际的。我们可以使用下一个代码而不是带有 goto 语句的丑陋版本吗?

    var variable = 2;
    switch (variable)
    {
    case 2:
    Console.WriteLine("variable is >= 2");
    goto case 1;
    case 1:
    Console.WriteLine("variable is >= 1");
    break;
    
    
    }
    

    可以用下一个更简洁的代码代替:

    if (variable >= 2)
    {
    Console.WriteLine("variable is >= 2");
    }
    if (variable >= 1)
    {
    Console.WriteLine("variable is >= 1");
    }
    

    【讨论】:

      猜你喜欢
      • 2023-03-16
      • 2013-07-12
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多