2

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

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

  • 它有任何性能影响吗?

  • 捕获、嵌套和重新抛出异常的含义是什么?

4

5 回答 5

4

唯一的潜在问题是您正在捕获非特定的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;
}

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

来自评论:

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

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

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

但是其他异常(例如SqlException无法期望调用者处理的异常)会被展开传播。

于 2012-09-26T14:15:22.230 回答
2

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

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

于 2012-09-26T13:54:55.460 回答
2

应该避免这种情况吗?

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

它有任何性能影响吗?

可能,是的,但我怀疑它是否真的很重要。一开始并不便宜。

捕获、嵌套和重新抛出异常的含义是什么?

好处:

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

缺点:

  • 仅捕获可能从您的库中抛出的一种类型的异常而不捕获其他异常更难。
  • 它在显示时给异常文本添加了很多混乱。
于 2012-09-26T13:56:06.373 回答
1

好的,作为一个真正的快速概述,当在 try catch 块中捕获异常时,它必须收集整个堆栈以进行跟踪。抛出任何类型的异常实际上都是相当昂贵的,但是当你将 throws 嵌套在 catch 块内时,它会成倍增长。因此,实际上,只有在您确切知道抛出异常的原因并计划通过尝试处理它的情况下,您才应该抛出异常。这主要是在您创建 API 时出现的情况,并且无法预测其他开发人员可能如何使用您的库。

如果您正在为自己的应用程序编写代码,则应完全避免抛出异常,因为您只是将其抛给自己(基本上)。在这种情况下,您应该处理如果抛出异常而不是抛出您自己的异常会发生什么。

与 Python(我喜欢它,但范式不同)和其他“oops”语言不同,通过 C# 中的异常处理来控制流并不是一个好习惯。

在 C# 下,try、throw 和 catch 块对性能的影响有多大

支持或反对使用 try catch 作为逻辑运算符的论据

C#中的异常处理

C# 异常(检查这个)

CA1031:不捕获一般异常

于 2012-09-26T13:57:49.897 回答
1

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

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

于 2012-09-26T13:57:58.250 回答