C# 什么时候处理异常?
我正在编写一个应用程序,可以通过多个步骤为任务提供信息。我有一些类似于下面的代码,我想知道这是否是处理异常的正常方法。这段代码可能永远不会被其他人看到,但它可能是,所以我想知道我正在像任何人所期望的那样处理异常C# 什么时候处理异常?,c#,exception-handling,C#,Exception Handling,我正在编写一个应用程序,可以通过多个步骤为任务提供信息。我有一些类似于下面的代码,我想知道这是否是处理异常的正常方法。这段代码可能永远不会被其他人看到,但它可能是,所以我想知道我正在像任何人所期望的那样处理异常 IEnumerable<Task> Tasks; foreach(var task in Tasks) { try { //boiler plate prep for task (loading libraries, connecting, logging sta
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()
{
}
}
i可数任务;
foreach(任务中的var任务)
{
尝试
{
//锅炉板准备任务(加载库、连接、记录启动等)
foreach(task.Steps中的var步骤)
{
尝试
{
step.Execute();
}
捕获(例外情况除外)
{
LogStepError(步骤,ex);
投掷;
}
}
//通知各方任务已成功完成,记录任务完成
}
捕获(例外情况除外)
{
LogTaskFailure(任务);
}
最后
{
//密切联系等
}
}
接口ITaskStep
{
void Execute()
{
}
}
我还想补充一点,任务步骤正在实现ITaskStep接口,因此Execute的实现不是我自己的(在本例中是这样的,但是有人可以实现接口)。我的代码只是加载库并运行任何iTask及其ITaskSteps。当我有一个任务列表,即使其中一些任务失败,我也要完成类似次数的任务。事实上,有时我知道有一个很好的机会失败,但我不想打破循环,直到所有步骤都完成 我认为这很有意义。如果for循环中只发生了
step.Execute()
i可数任务;
foreach(任务中的var任务)
{
尝试
{
//锅炉板准备工作
}
捕获(例外情况除外)
{
LogTaskFailure(任务);
继续;
}
foreach(task.Steps中的var步骤)
{
尝试
{
step.Execute();
}
捕获(例外情况除外)
{
LogStepError(步骤,ex);
LogTaskFailure(任务);
打破
}
}
}
类任务步骤
{
私有void Execute()
{
//做一些事情,不要捕捉任何异常
}
}
这样您就不会重新显示异常。我想我可能是这样写的,但是您的方法也可以工作
foreach(var step in task.Steps)
{
try
{
step.Execute();
}
catch(Exception ex)
{
LogStepError(step, ex);
LogTaskFailure(task);
break;
}
}
您可能希望使用返回变量来处理任务的完成,并在整个代码中使用Exception来捕获任何通用异常
例如:
try{
foreach(var step in task.Steps)
{
if(!step.Execute()){
break;
}
}
}catch(Exception ex)
{
}
您正在捕获所有异常,这是可以的,正如您提到的,这是最常见的方法,但我认为这不是正确的方法
我认为你应该抓住具体的例外情况。如果你这样做了,你可以把它们分开,你会注意到有些例外情况你根本无法处理,但有些例外情况你可以处理。代码将变得更好、更健壮,因为您将确切地知道代码上发生了什么
这是一个例子:
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
}
继续捕获异常以记录它们的存在。但是,如果您还没有真正解决导致抛出异常的问题,那么请重新抛出该异常以供调用方处理。不要吞下它
上面的代码捕获一个taskisboguseException
和一个PrinterOnFireException
并以相同的方式处理它们:记录它并继续执行下一个任务。用一个虚假的任务来做这件事是可以的,因为你已经完成了任务,但是如果你发现了一个printeronfirefexception
,并且没有重新启动它,那么天哪,打印机最好不要仍然着火
如果您不打算重新调用,那么只捕获代码知道如何处理的特定异常类型。让其他所有内容(无论是您不知道如何处理的内容,还是您从未想过的内容)传播到下一个可用的异常处理程序。锅炉板准备是在循环之外发生的一些其他内容,我想在try/catch中进行包装。它提取一些库依赖项并将它们写入磁盘以备将来使用,以及连接到远程系统等。使用此代码,如果boiler plate代码引发异常,则不会执行更多任务,这不是我想要的。我还需要使用finally块来处理任何连接。我想我的第一个例子不是最具代表性的。我计划在将来做类似的事情,但我需要先弄清楚一般的设置。
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
}