何时处理异常?

时间:2009-07-23 16:47:34

标签: c# exception-handling

我正在编写一个可以通过多个步骤提供任务的应用。我有一些类似于下面的代码,我想知道这是否是处理异常的常规方法。这个代码可能永远不会被其他人看到,但它可能是,所以我想知道我正在按照任何人的预期处理异常。

IEnumerable<Task> Tasks;

foreach(var task in Tasks)
{
 try
 {
   //boiler plate prep for task (loading libraries, connecting, logging start, etc)

   foreach(var step in task.Steps)
   {  
      try
      {
        step.Execute();
      }
      catch(Exception ex)
      {
        LogStepError(step, ex);
        throw;
      }
    }

    //Notify parties task has been completed successfully, log task completion
  }
  catch(Exception ex)
  {
      LogTaskFailure(task);
  }
  finally
  {
    //close connections, etc
  }
}



interface ITaskStep
{
    void Execute()
    {

    }            
}

我还想补充一点,任务步骤正在实现ITaskStep接口,因此Execute的实现不是我自己的(在这个例子中,有人可以实现接口)。我的代码只是加载库并运行任何ITasks及其ITaskSteps。

6 个答案:

答案 0 :(得分:7)

继续并捕获异常以记录它们的存在。但是如果你还没有真正解决导致抛出异常的问题,那么请重新抛出它以便调用者处理。不要吞下它。

上面的代码捕获TaskIsBogusExceptionPrinterOnFireException并以相同的方式处理它们:记录它并继续执行下一个任务。使用虚假任务执行此操作很好,因为无论如何你已经完成了任务,但是如果你抓到PrinterOnFireException并且不重新抛出它,那么通过高兴,打印机最好还是不会着火。 / p>

如果您不打算重新抛出,那么只捕获您的代码知道如何处理的特定异常类型。让其他一切(你不知道如何处理的东西,或你从未想过的东西)传播到下一个可用的异常处理程序。

答案 1 :(得分:2)

如果{for循环中发生step.Execute()是唯一发生的事情,则以下情况可能更好:(为澄清而编辑)

IEnumerable<Task> Tasks;

foreach(var task in Tasks)
{
   try
   {
     //boiler plate prep for task
   }
   catch(Exception ex)
   {
     LogTaskFailure(task);
     continue;
   }
   foreach(var step in task.Steps)
   {  
      try
      {
        step.Execute();
      }
      catch(Exception ex)
      {
        LogStepError(step, ex);
        LogTaskFailure(task);
        break;
      }
    }
}

class TaskStep
{
    private void Execute()
    {
       //do some stuff, don't catch any exceptions
    }            
}

这样您就不会重新抛出异常。

答案 2 :(得分:2)

你正在捕捉所有可以正常的例外情况,正如你所提到的那样,这是最常见的方法,但我不认为这是正确的。

我认为你应该抓住具体的例外情况。如果你这样做,你可以将它们分开,你会注意到有些例外情况是你根本无法处理的,但是还有其他例外情况你可以处理。由于您将准确了解代码中发生的情况,因此代码将更好,更强大。

这是一个例子:



try
{
     //Your stuff
}
catch(DivideByZeroException ex)
{
   //Could you manage this?
}
catch(NullReferenceException ex)
{
   //Could you manage this one?
}
catch(IOException ex)
{
      //What about this one?
}
finally
{
      //Any cleanup code
}

答案 3 :(得分:0)

当我有一个我想要完成的任务列表时,即使其中一些任务失败,我也做了类似的事情。实际上有些时候我知道很有可能会失败,但我不想在所有步骤完成之前突破循环。

我认为这很有道理。

答案 4 :(得分:0)

我想我可能会这样写,但你的方法也可以。

foreach(var step in task.Steps)
       {  
          try
          {
            step.Execute();
          }
          catch(Exception ex)
          {
            LogStepError(step, ex);
            LogTaskFailure(task);
            break;
          }
        }

答案 5 :(得分:0)

您可能希望使用return变量处理任务的完成,并在整个代码片段上使用Exception来捕获任何一般异常。

示例:

try{
foreach(var step in task.Steps)
       {  
            if(!step.Execute()){
                break;
            }

        }
}catch(Exception ex)
{
}