c# - .NET 库的异常处理模式 - 处理、无人值守还是重新抛出?

标签 c# .net exception design-patterns class-library

我正在编写一个 C# 库,其 DLL 稍后将由其他应用程序的代码使用。

当库中存在可能引发异常(例如 System.IO.IOException )的语句时,我应该立即捕获它还是应该将其留待程序捕获使用它的应用程序的名称?

我问这个是因为,我还没有在我的库中捕获异常。调试我的应用程序(使用该库)时,Visual Studio 将其显示为库中的未处理的异常。但是当我>继续时,程序继续并且异常被应用程序捕获。看起来运行良好。

现在,这样做可以吗?即部署应用程序时是否会出现任何问题?或者它应该绝对被捕获在图书馆本身中?或者 MSDN 是否在某个地方建议了比这更好的“最佳实践”?

最佳答案

编写一个好的库是一门艺术和科学。假设您已经决定提供的功能并向库的使用者公开相关的 API,那么似乎有一个问题尚未解决 - 异常处理。

一般来说,库代码执行期间引发的异常可以分为两类: 1. 取决于库的实现和功能。 2. 依赖于消费者或系统并且超出了您的图书馆的兴趣范围。

恕我直言,最佳实践是定义库代码引发的所有异常,并从 ApplicationException 派生它们。或者更好的是从相关的 .NET 异常中使用您的库特定前缀,即: <LibShortName>FormatException<LibShortName>InvalidOperationException 。然后,如果您的库应向客户端代码抛出异常,请使用库派生异常。

如果在库外部引发了异常,并且从您的库功能角度来看它们是有意义的,您可以捕获它们,并抛出包含已捕获异常作为内部异常的新库异常,或者使用 <LibShortName>AggregateException在将异常暴露给客户端之前创建异常链接。

上述方案在许多流行的 .NET 库中使用,例如 SharpSkia。还有其他方法可以解决这个问题,但是,我发现上述方法对于图书馆消费者来说信息量最大 - 他们获得尽可能多的有关错误的信息。此外,他们可以轻松地使用基于类型的模式来捕获和处理异常。

编写优秀库的最重要方面之一是性能。为了获得最适合您的库,请不要在代码中使用异常来控制流。异常应该专门用于错误情况。违反上述模式的不良设计的一个很好的例子是 ANTLR C# parser framewrok事情 v2。在某些阶段,库使用异常来控制解析逻辑,这是极其低效的。后来它被重构为仅在错误情况下使用异常,从而将性能提高了几个数量级。

最后,关于设计 .NET 库 API 的最佳书籍之一是:

读这些可能会很有趣的是关于 API Reviews 的讨论在来自 .NET Core corefx 的封闭和开放问题中存储库有点旧,但仍然是一篇经典的 Krzysztof Cwalina 博客文章,标记为 General API Design

关于c# - .NET 库的异常处理模式 - 处理、无人值守还是重新抛出?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47287931/

相关文章:

c# - Dictionary/IDictionary 中的行为不一致

Java:调用函数如何不处理子函数的异常?

java - 使用异常或者使用多个try catch java

java - 如何从间接线程中捕获异常?

c# - 仅在 VB 中的 .NET 集合

.NET NUnit 测试 - Assembly.GetEntryAssembly() 为 null

c# wpf 错误 (System.InvalidOperationException)

c# - 是否可以从存储过程访问 Azure Blob?

c# - Asp.net C#上传控件

c# - 如何使用 webservice C# 为基于事件的函数应用异步/等待?