从catch块中抛出嵌套的exception……这是明智的吗?

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

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

  • 它有任何性能影响吗?

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

唯一可能的问题是您捕获的是非特定的Exception ,因此不符合exception处理指南 。

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

 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,就会发生exception事件,你可能并不关心包装它的额外开销。

来自评论:

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

我不同意这一点,尽管这是公认的主观。 包装exception的库的一个示例是SqlMembershipProvider ,它在ProviderException包装一些特定的exception,例如:

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

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

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

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

这应该避免吗?

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

它有任何性能影响吗?

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

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

好处:

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

缺点:

  • 只捕获可能从您的库中抛出的一种类型的exception,而不是捕获其他exception则更难。
  • 它在显示exception文本时会增加很多混乱。

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

try-catches确实强加了他们自己的性能开销,但是我没有看到任何使得这个块比任何其他类似块更糟糕的东西。

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

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

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

在C#下,多少性能命中是try,throw和catch块

支持使用try catch作为逻辑运算符的参数

C#中的exception处理

C#exception(检查一下)

CA1031:不要抓住一般例外情况