从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:不要抓住一般例外情况