在这种情况下使用“goto”是否可以接受?

时间:2010-10-17 20:02:16

标签: c# coding-style goto

以下是伪代码:

myGoto:
try
{
   // do some db updating
   myDB.doOptimisticConcurrency();

} catch (MyConcExeption ex) {

   if (tried < fiveTimes) {
       myDB.Refresh();
       tried++;
       goto myGoto;
   }

}

我在一个方法中有几个try-catch块,我不想从头开始为每个抛出的异常重新调用我的方法。在这种情况下使用goto是否可以接受?

6 个答案:

答案 0 :(得分:16)

您可以将其更改为:

while (tried < fiveTimes)
try
{
   // do some db updating
   myDB.doOptimisticConcurrency();
   break;
}
catch (MyConcExeption ex)
{
   tried++;
   myDB.Refresh();
}

答案 1 :(得分:13)

我不会使用“goto” - 但你可能想写一个小帮手方法。例如:

public static void TryMultiple<E>(Action action, int times) where E : Exception
{
    E lastException = null;
    for (int i = 0; i < times; i++)
    {
        try
        {
            action();
            return; // Yay, success!
        }
        catch (E exception)
        {
            // Possibly log?
            lastException = exception;
        }
    }
    throw new RetryFailedException("Retry failed " + times + " times",
                                   lastException);
}

这只是解决方案的草图 - 您需要相应地调整它。无论如何,这基本上允许您以可重用的方式在半被接受的异常面前执行重试。您可能会使用lambda表达式来表达操作,或者有时只使用方法组来表示单个方法调用:

TryMultiple<MyConcurrencyException>(myDB.doOptimisticConcurrency, 5);

答案 2 :(得分:3)

你可以使用一个循环。

答案 3 :(得分:2)

使用goto几乎是不可接受的,它导致spaghetti code并使代码的可读性降低。

在你的情况下,一个简单的循环会使你的代码更具可读性。

alt text

答案 4 :(得分:1)

如果情况不是那么特殊,你不应该抛出异常。为什么不向该方法添加重试参数并仅在超出重试次数时在内部抛出异常?

编辑:正如其他人所说,循环也是一个更好的选择。但是,这看起来像你的方法,而不是一些你无法修改的库中包含的方法。如果我是正确的,我仍然会使用retry参数,并且只有在所有重试失败时才抛出异常。如果您希望此方法有时会在第一次尝试时失败,那不应该是例外。

答案 5 :(得分:-1)

这要好得多:

private void MyMethod()
{
   MyMethod(5);
}    

private void MyMethod(int triesLeft)
{
   if(triesLeft == 0)
      return;  // or throw

   try
   {
      // do some db updating
      myDB.doOptimisticConcurrency();
   }       
   catch (MyConcExeption ex) 
   {
       myDB.Refresh(); 
       MyMethod(triesLeft - 1);
   }
}