C#中的异常处理:多次尝试/捕获与一次

时间:2008-12-16 18:53:55

标签: c# exception

每种方法有多个try{} catch{}语句是不错的做法?

12 个答案:

答案 0 :(得分:14)

在我看来,最好让每个方法只处理一个任务。因此,您很少需要在单个方法中拥有多个try / catch块。但是,我没有看到任何问题。

正如Lisa所指出的那样,你应该捕获特定的异常,而只能捕获方法实际可以处理的异常。

答案 1 :(得分:6)

最好有一次尝试/ catch多次捕获以不同方式处理每种类型的异常。

答案 2 :(得分:6)

如果您知道事先可能发生的异常类型,那么您可以尝试一次并捕获每个异常,如果您想以不同方式处理它们。例如:

try
{
    // a bunch of risky code
}
catch (SpecificException1 ex1)
{
     // handle Specific Exception 1
}
catch (SpecificException2 ex2)
{
     // handle Specific Exception 2
}
catch (SpecificException3 ex3)
{
     // handle Specific Exception 3
}
catch (Exception ex)
{
     // handle an exception that isn't specific
}

答案 3 :(得分:6)

IMO如果您知道可能发生的异常,则不应使用try ... catch来获取错误。

不要用例外编程....所以我不认为倍数是个好主意。

答案 4 :(得分:4)

通常,我往往比finallycatch。通常,您可以使用异常执行特定的,所以让它冒泡。但是finally确保你可以干净利落地关闭等等。

答案 5 :(得分:4)

对于复杂的生产级场景,拥有多个try-catch语句是一种可怕的做法,将这些语句置于业务逻辑中是非常不灵活的做法。

Windows云计算团队(他们的代码必须高效可靠)似乎坚持使用Exception Handling Action Policies

此代码是更好的替代品:

// perform action within the policy
policy.Do(() => repository.AddMessages(someMessages));

虽然较旧的代码块看起来像:

try
{
  repository.AddMessages(someMessages);
}
catch (Exception1 ex)
{
  // dosomething...
}
catch (Exception2 ex)
{
  // second handler
}
catch (Exception3 ex)
{
  // third handler
}

或(这是Microsoft Enterprise Library在硬编码操作策略中提供可配置异常处理程序的方式):

try
{
  repository.AddMessages(someMessages);
}
catch (Exception ex)
{
  bool rethrow = ExceptionPolicy
    .HandleException(ex, "Global Policy");
  if (rethrow)
  {
    throw;
  }
}

另外,如果你有action policy,你可以告诉它(配置)记录,休眠,重试某些类型的异常,而不是简单地失败或做一些其他硬编码的动作。

答案 6 :(得分:2)

根据经验,每个方法都应该处理一个任务 - 这个最佳实践来自一个测试驱动的环境,这使得生成测试变得更加容易。编写“上帝”程序的测试计划本身就更加困难。

因此,最佳做法是仅在可能失败的项目周围使用try {} catch {},并且只在通常捕获有用处理的异常的位置使用。

不要使用单个try {} catch {}来包装方法的全部内容,从而消除对正确编码实践的责任。

处理异常是一项昂贵的操作 - 在必要时捕获它们并编写可防止其他地方发生异常的代码。在某些情况下,防止异常本身并不简单,但可以使用try / catch有效地捕获和使用它 - 例如检查文件操作的排他性。

当你使用try / catch时做出有意识的决定,不要因为你可以扔掉它,这是懒惰的。问问自己“我在这里需要它吗?”,或者“我可以使用更便宜和/或更结构化的方法来做到这一点吗?”。

答案 7 :(得分:1)

我会说这取决于。对我来说,看起来有点草率,所有这些尝试捕获到处都是。我尝试整合到一个有许多捕获量的try块。有时这不起作用,你可能需要将它们分开,但为了保持可读性,至少我更喜欢它。

此外,如果您的方法过长,您可以提取方法来分发您的尝试捕获。

答案 8 :(得分:1)

这取决于。异常处理的目的就是在发生时处理运行时异常。

我通常只有一个catch catch / catch然后我在我知道有可能抛出异常(类型转换等)的代码区域周围放置try catch块。

答案 9 :(得分:1)

我发现整合了许多代码行,每行代码都可以将自己的异常抛入一个try块中,并且捕获很多代码很难读取代码。仅仅通过查看代码,什么行代码抛出什么异常就不明显了。在我看来,尝试捕获应包含尽可能少的代码;只有可以抛出给定异常的代码。如果您正在编写的方法包含多个尝试捕获,则应将它们分别提取到自己的方法中。

如果您的方法中有多个方法调用会引发相同的异常,那么这一点就变得更加重要了。然后它们应该处于单独的try catch中,因为当您捕获异常时,通常希望将其包装在适合当前抽象的新异常中,并附带相关的错误消息。如果在同一个try catch中有两个语句,则您将失去为不同错误提供不同错误消息的机会。

Object operationResult;
try {
  operationResult = remoteService.performRemoteOperation();
} catch (RemoteException ex) {
  throw new BusinessException("An error occured when getting ...", ex);
}

// use operation result

答案 10 :(得分:1)

使用多个try / catch块的优点是它明确地将您正在尝试的操作与预期的异常配对。一般来说,如果抛出它的条件是不可恢复的(除非您正在执行类似于记录诊断的特定异常),否则您不会捕获异常。像这样的代码:

try
{
   Operation1();
}
catch (MySpecificException1)
{
   RecoverFromExpectedException1();
}
try
{
  Operation2();
}
catch (MySpecificException2)
{
   RecoverFromExpectedException2();
}

可能有点冗长,但这是使用流控制异常的结果。重要的是你可以通过查看这段代码告诉第一个操作可能抛出一个特定的异常,并且你的代码知道如何从这个异常中恢复并继续进行第二个操作。并且try / catch块没有做任何其他事情但是那个。

答案 11 :(得分:1)

每种方法都有1次尝试/捕获是不好的做法。

完全发明了异常,因此我们可以编写更少的错误处理代码,而不是像其他一些答案所建议的那样。

在异常之前,您必须通过测试返回值来检查每行代码是否成功,如果出现错误,则必须通过返回将其传递回调用堆栈。这意味着每种方法都必须进行测试和返回。发明了异常,因此方法不必在整个地方都需要这些检查,并且您可以拥有一系列可读的代码行,因为它们不会被错误处理所掩盖。

所以...建议是,你应该拥有最少的尝试/捕获量,这应该意味着大多数方法都不需要。

但是,这里有一些应该使用它们的地方:

  • 当操作失败时(写入日志文件或向用户显示错误消息),只有在您知道程序可以继续并且现在因为一个操作失败而现在不处于损坏状态时才执行此操作。操作必须相互隔离。
  • 在您的Main方法中记录因程序终止而未在别处处理的任何异常。
  • 在您可以采取行动的地方,例如重试某项操作或回退到较低的操作模式。
  • 如果API不佳,则无法让您测试需要处理的条件。例如,如果要打开文件,并且API未提供DoesFileExist(),则可以先调用。

我现在无法想到其他地方......那是因为尝试/捕获应该很少而且很远!

当抛出任何异常时,我总是将调试器设置为中断。它很少会中断,因为异常是例外。