我想在我的库中实现自定义异常处理,以便我知道异常发生的位置,所以我这样做:
try
{
DoSomething();
}
catch(Exception ex)
{
//LibraryException refers to any exception in the libraries exception hierarchy
throw new LibraryException(ex.Message, ex);
}
这应该避免吗?
它是否有任何性能影响?
捕获,嵌套和重新抛出异常有什么含义?
答案 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
答案 4 :(得分:1)
在上下文中,抛出更具体的异常通常是一个好主意,提供 LibraryException来自您自己的问题域,并向开发人员提供更具体的信息,以便他们可以说“啊,一个库异常意味着发生了某类错误之一。“
尝试捕获确实强加了他们自己的性能开销,但是我没有看到任何使得这个块比任何其他类似块更糟糕的事情。