【问题标题】:Should I use goto statement? [closed]我应该使用 goto 语句吗? [关闭]
【发布时间】:2012-11-07 17:10:10
【问题描述】:

我有一段代码如下:

try
{
Work:

   while(true)
   {
      // Do some work repeatedly...
   }
}
catch(Exception)
{
   // Exception caught and now I can not continue 
   // to do my work properly

   // I have to reset the status before to continue to do my work
   ResetStatus();

   // Now I can return to do my work
   goto Work; 
}

与使用goto 相比,有没有更好的选择?或者这是一个好的解决方案?

【问题讨论】:

  • 为什么不把你的try catch放在while里面呢?那么就不需要 goto...
  • 为什么要投反对票?这是一个合理的问题
  • 我认为它被否决了,因为有人提到 Jeho ...我的意思是 goto ;) 很多人都非常讨厌 goto,虽然它几乎从来没有必要或明智地使用,但它仍然存在一个理由,这不是最邪恶的陈述。
  • @AlexK.,我没有投反对票,但我确实投票结束了。按照目前的措辞,这个问题没有真正的答案。很多人可以就最佳实践给你意见,大多数人都会向 goto 致敬,但总的来说,这是一个意见问题。
  • @AlexK.:我认为是因为它基本上是代码审查,而不是本网站的内容。虽然我说这不是作为反对者之一,但我考虑出于这个原因投票结束。

标签: c# goto


【解决方案1】:

听起来你真的想要一个循环。我会写成:

bool successful = false;
while (!successful)
{
    try
    {
        while(true)
        {
            // I hope you have a break in here somewhere...
        }
        successful = true;
    }
    catch (...) 
    {
        ...
    }
}

您可能想改用do/while 循环;我倾向于更喜欢直接的 while 循环,但这是个人喜好,我可以在这里看到它可能更合适。

不会使用goto。它往往会使代码更难遵循。

当然,如果您真的想要无限循环,只需将try/catch 放入循环中即可:

while (true)
{
    try
    {
        ...
    }
    catch (Exception)
    {
        ...
    }
}

【讨论】:

  • @Fake.It.Til.U.Make.It:恐怕我不明白你的意思。
  • 这似乎不相等,他有 while(true) 不会在成功时退出,除非我错过了什么。
  • 这是这里唯一明智的答案。恭喜获得 500K。
  • 他正在调用标签Work,它在try 块中来自catch 块..它有效
  • @kekekela 确切的代码等效性从来都不是答案的要求,并且 OP 没有提供足够的信息来判断他原始代码的确切意图是什么。
【解决方案2】:

Goto 很少适合使用。使用会使 99% 的查看您的代码的人感到困惑,甚至在技术上正确使用它也会大大减慢对代码的理解。

在大多数情况下,重构代码将消除对goto 的需求(或使用欲望)。 IE。在您的特定情况下,您可以简单地将 try/catch 移动到 while(true) 内。将迭代的内部代码制作成单独的函数可能会更简洁。

while(true)
{
  try
  {
      // Do some work repeatedly...
  }
  catch(Exception)
  {
   // Exception caught and now I can not continue 
   // to do my work properly

   // I have to reset the status before to continue to do my work
   ResetStatus();
  }
}

【讨论】:

  • 这不等同于尼克的代码。他的代码成功退出。
  • @snowbear:我假设 while(true) 将事物保持在无限循环中。不过,以这种新形式退出 while 循环同样容易......
  • 它看起来和我一样,while(true) 是如何成功退出的?
  • @Snowbear:成功时它会从哪里退出?退出循环的唯一方法是抛出异常,这将导致转到,然后转到标签并直接返回循环。我错过了什么吗?
  • @Snowbear,我不确定原始样本在哪里成功退出......按原样从问题中复制粘贴 - 正如乔恩的回答所暗示的那样,可能会错过意图......
【解决方案3】:

将 try/catch 移到 while 循环中似乎更有意义。然后您可以处理错误,循环将正常继续,而无需使用标签和 goto 路由控制流。

【讨论】:

    【解决方案4】:

    在每次迭代中捕获并恢复状态,即使在外部捕获也一样,但您仍处于循环中,您可以决定是继续还是中断循环。

    ALSO: 从一开始就捕获Exception 是错误的(如果您捕获StackOverflowExceptionMemoryLeachException,您会怎么做 - 编辑:这只是举例,检查文档以了解您可以在现实中捕捉到什么)。捕获您希望抛出的具体类型的异常。

    while(true)
    {
        try
        {
            // Do some work repeatedly...
        }
        catch(FileNotFoundException) //or anything else which you REALLY expect.
        {
            // I have to reset the status before to continue to do my work
            ResetStatus();
            //decide here if this is till OK to continue loop. Otherwise break.
        }
    }
    

    对于那些在 cmets 中非常聪明的人:Why don't catch general exception

    【讨论】:

    • 实际上,StackoverflowException 一开始就无法被捕获,就像其他一些真正致命的异常(即 OOM)一样。
    • 这只是一个例子。捕获异常是错误的 - 这就是我的意思。
    • 我不同意这一点,但这与手头的问题无关,所以我认为在 cmets 中讨论它没有意义。
    • 请阅读更多关于为什么不捕获一般异常的信息。我刚刚用链接更新了答案。享受你真正的思维方式!
    • 还没有被否决但是...这应该是评论,因为它绝对与问题无关(通常必须更改示例代码以使其变小并显示问题)...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    相关资源
    最近更新 更多