C#,自定义异常的使用

C#, usage of custom exceptions

我需要做一个简短的前提:我是一个有20多年经验的软件架构师,不是初级问路。这并不是说“我什么都知道”(事实恰恰相反),而只是为了提供背景并说明我对我认为是常识和最佳实践的事情产生了合理的怀疑,并且已经这样做了所有这一切时间.

我正在为不同的客户开展不同的项目。我总是检查方法的参数是否为 null 以及其他无效状态。您可以在我的代码中找到的常见前提条件检查是:

if (param == null) { throw new ArgumentNullException(nameof(param)); }

this.myField = myParam ?? throw new ArgumentNullException(nameof(myParam));

另外请记住,我很少使用异常,我不会对异常进行用户输入验证,我只是用它们来检查代码中的 and/or 信号无效状态,从而导致编程错误。在我的代码中根本找不到 try/catch 块。

我的一位客户刚刚问我,没有太多争论的余地,用自定义异常替换任何类似的事件。这意味着我要定义 CustomerNameArgumentNullException、CustomerNameFileNotFoundException 等,并在我会使用标准异常的地方使用它们。

现在我会遵守,我无权争论客户的请求,但他们的首席程序员在这一点上非常强调这是正确的方法,使用默认异常会降低代码的可读性,而且自定义异常可以更轻松地了解 Azure Application Insights 中的情况。我试图指出他有引发异常的方法的完全限定名,这样他就可以知道哪个程序、哪个程序集和名称空间等等,但同样,没有太多争论的余地,这不是我的位置这样做。

所以我一直在想他是否真的是对的,而我一直都在做异常错误。如果有人有更多见解 and/or 一些 material 我可以阅读支持该理论的内容。

谢谢。

硬币有两面。当然 MS 推荐 this

使用自定义异常既有优点也有缺点。

优点:

  1. 抽象
  2. 您可以在引发异常之前记录遥测数据。如果不是自定义异常,你必须捕获异常,记录数据并重新抛出。
  3. 根据 app/services 等
  4. 的需要自定义异常和错误处理

缺点:

  1. 如果您抛出自定义异常,遥测数据将没有堆栈跟踪。
  2. 代码维护和严格测试

还有其他各种事情需要考虑,但是捕获异常、记录指标然后重新抛出(以保留堆栈跟踪)相同的异常是昂贵的。

只是我的想法。

虽然通常我建议像这样的问题应该基于意见关闭,但在这种情况下 really clear guidance from Microsoft:

Use the predefined .NET exception types

Introduce a new exception class only when a predefined one doesn't apply. For example:

  • Throw an InvalidOperationException exception if a property set or method call is not appropriate given the object's current state.

  • Throw an ArgumentException exception or one of the predefined classes that derive from ArgumentException if invalid parameters are passed.

换句话说,您的客户要求您违背平台作者的指导。

您可能无法改变客户的想法以遵循指导,但您可以确信您的方法是推荐的方法,而他们的方法与此相反。

遵循这样的约定在开源项目中尤为重要 - 当只有您的团队使用代码时,决定拥有自己的约定是一回事,但如果应用程序使用 10 个不同的开源库, 每个都决定创建自己的约定,那是一场噩梦。