从catch块中抛出嵌套的异常......这是明智的吗?

时间:2012-09-26 13:51:10

标签: c# .net exception exception-handling

我想在我的库中实现自定义异常处理,以便我知道异常发生的位置,所以我这样做:

try
{
    DoSomething();
}
catch(Exception ex)
{
    //LibraryException refers to any exception in the libraries exception hierarchy
    throw new LibraryException(ex.Message, ex);
}
  • 这应该避免吗?

  • 它是否有任何性能影响?

  • 捕获,嵌套和重新抛出异常有什么含义?

5 个答案:

答案 0 :(得分:3)

唯一可能的问题是您捕获的是非特定Exception,因此不符合exception handling guidelines

以下其中一项更符合这些准则:

try
{
    DoSomething();
}
catch(SomeException ex)
{
    throw new LibraryException(ex.Message, ex);
}

或:

try
{
    DoSomething();
}
catch(Exception ex)
{
    if (ex is SomeException || ex is SomeOtherException)
    {
        throw new LibraryException(ex.Message, ex);
    }
    throw;
}

至于性能,一旦抛出Exception,就会发生异常情况,你可能并不关心包装它的额外开销。

来自评论:

  

在大多数情况下,当库选择包装异常时,它将包装在库范围之外抛出的所有异常,...

我不同意这一点,尽管它确实是主观的。包装异常的库的一个示例是SqlMembershipProvider,它包含ProviderException中的一些特定异常,例如:

try
{
    new Regex(this._PasswordStrengthRegularExpression);
}
catch (ArgumentException exception)
{
    throw new ProviderException(exception.Message, exception);
}

但是其他例外情况,例如调用者无法处理的SqlException会被解包传播。

答案 1 :(得分:2)

如果它为您的架构添加了抽象和/或清晰度,那么这是一个很好的做法。

它使异常更明确,并可能隐藏更高层的低层细节。例如,在数据访问层中,您可以捕获SqlExceptions并改为抛出DataAccessExceptions,以便较高层不“知道”您使用SQL Server作为数据存储。

答案 2 :(得分:2)

  

应该避免这种情况吗?

这是一个偏好问题。在某些情况下,它可能是有利的,在某些情况下是有害的,并且在大多数情况下是两者中的一些。在某些情况下,您可以看到现有库完成此操作,还有其他库选择不这样做。

  

它是否有任何性能影响?

可能是的,但是我怀疑这是非常重要的。开头并不便宜。

  

捕获,嵌套和重新抛出异常有什么含义?

的优点:

  • 调用您的方法的人可以轻松捕获从您的库中抛出的异常。
  • 隐藏来自来电者的图书馆的实施细节。
  • 允许调用者轻松地从库中捕获异常。如果没有这个,如果他们试图捕获一个无效的参数异常,它可能来自您的库或其他代码。他们可能只想捕获从其他地方抛出的争论异常。

缺点:

  • 很难抓住可能从你的图书馆抛出的一种类型的异常,而不是抓住其他异常。
  • 在显示异常文本时,它会增加很多混乱。

答案 3 :(得分:1)

好的,作为一个真正的快速概述,当在try catch块中捕获异常时,它必须收集整个堆栈以进行跟踪。抛出任何类型的异常实际上都是相当昂贵的,但是当你在catch块中嵌入throws时它会呈指数级增长。所以,如果您确切知道为什么要抛出它并计划通过尝试处理它,那么您应该只抛出异常。当您创建API时,大多数情况都是如此,并且无法预测其他开发人员如何使用您的库。

如果你是为自己的应用程序编写的,你应该避免抛出异常,因为你只是把它扔给自己(基本上)。在这种情况下,您应该处理如果抛出异常而不是自己抛出的情况。

与Python(我喜欢但不同的范例)和其他“oops”语言不同,在C#中通过异常处理来控制流是不好的做法。

Under C# how much of a performance hit is a try, throw and catch block

Arguments for or against using try catch as logical operators

Exception Handling in C#

C# Exception (Check this one out)

CA1031: Do not catch general exceptions

答案 4 :(得分:1)

在上下文中,抛出更具体的异常通常是一个好主意,提供 LibraryException来自您自己的问题域,并向开发人员提供更具体的信息,以便他们可以说“啊,一个库异常意味着发生了某类错误之一。“

尝试捕获确实强加了他们自己的性能开销,但是我没有看到任何使得这个块比任何其他类似块更糟糕的事情。