1

以下是伪代码:

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

} catch (MyConcExeption ex) {

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

}

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

4

6 回答 6

16

您可以将其更改为:

while (tried < fiveTimes)
try
{
   // do some db updating
   myDB.doOptimisticConcurrency();
   break;
}
catch (MyConcExeption ex)
{
   tried++;
   myDB.Refresh();
}
于 2010-10-17T20:05:31.997 回答
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);
于 2010-10-17T20:07:10.877 回答
3

你可以只使用一个循环。

于 2010-10-17T20:05:00.350 回答
2

使用 goto 几乎是不可接受的,它会导致意大利面条式代码并使您的代码可读性降低。

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

替代文字

于 2010-10-17T20:02:49.537 回答
1

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

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

于 2010-10-17T20:05:50.023 回答
-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);
   }
}
于 2010-10-17T20:07:21.610 回答