简体   繁体   English

在 C# 中,是否有任何我不应该使用的内置异常?

[英]In C#, are there any built-in exceptions I shouldn't use?

Are there any Exceptions defined in the .NET Framework that I shouldn't throw in my own code, or that it is bad practice to? .NET 框架中是否有任何我不应该在自己的代码中抛出的异常,或者这是不好的做法? Should I write my own?我应该自己写吗?

You shouldn't throw any exception that is automatically thrown by the CLR due to user errors. 您不应抛出由于用户错误而由CLR自动抛出的任何异常。 For instance 例如

  • StackOverflowException StackOverflowException
  • NullReferenceException 的NullReferenceException
  • AccessViolationException AccessViolationException
  • etc ... 等......

The reason being is to do so creates confusion for people calling your API. 这样做的原因是为调用API的人造成了混乱。 Users should be able to distinguish between actively thrown exceptions by an API and exceptions that are not actively thrown (thrown by CLR). 用户应该能够区分API主动抛出的异常和未主动抛出的异常(由CLR抛出)。

The reason is that at actively thrown exception generally represents a known state in an API. 原因是主动抛出异常通常表示API中的已知状态。 If I call an API and it throwns an ArgumentException, I have a reasonable expectation that the given object is in a good state. 如果我调用一个API并抛出一个ArgumentException,我有理由期望给定的对象处于良好的状态。 It recognized a potentially bad situation and actively accounted for it. 它认识到一种潜在的不良情况并积极地对其进行说明。 On the other hand if it throwns a NullRefrenceException, that is an indication that the API encountered an unknown error and is now in an unreliable state. 另一方面,如果它抛出NullRefrenceException,则表明API遇到未知错误,现在处于不可靠状态。

Another lesser reason is that these exceptions behave differently when thrown by user code as opposed to the CLR. 另一个较小的原因是,当用户代码抛出而不是CLR时,这些异常的行为会有所不同。 For instance it's possible to catch a StackOverflowException if thrown by user code, but not if it's thrown by the CLR. 例如,如果用户代码抛出,则可能捕获StackOverflowException,但如果CLR抛出则不会。

EDIT Responding to Michael's comment 编辑回应迈克尔的评论

You also should not throw Exception, ApplicationException or SystemException directly. 您也不应该直接抛出Exception,ApplicationException或SystemException。 These exceptions types are too general to provide meaningful information to the code which calls your API. 这些异常类型过于笼统,无法为调用API的代码提供有意义的信息。 True you can put a very descriptive message into the message parameter. 如果是,您可以在message参数中添加非常具描述性的消息。 But it's not straight forward or maintainable to catch an exception based on a message. 但是根据消息捕获异常并不是直接或可维护的。 It's much better to catch it based on the type. 根据类型捕获它会好得多。

FxCop rule on this subject: http://msdn.microsoft.com/en-us/library/ms182338(VS.80).aspx 关于这个主题的FxCop规则: http//msdn.microsoft.com/en-us/library/ms182338( VS.80) .aspx

Most exception classes in the framework are not meant for reuse since they usually are crafted to signal some Framework specific error. 框架中的大多数异常类都不是为了重用,因为它们通常用于表示某些特定于框架的错误。 Like those mentioned by @JaredPar , they are used by the framework to indicate certain states in the framework. @JaredPar提到的那些一样,框架使用它们来指示框架中的某些状态。

There are literally tens, maybe hundreds, exceptions in the framework, so IMO it is more useful to list those that we should use. 在框架中有几十个,也许几百个例外,因此IMO列出我们应该使用的那些更有用。 At the top of my head, these are those I actively use: 在我的头脑中,这些是我积极使用的:

For other error conditions in user code, best practice is to create your own exception classes. 对于用户代码中的其他错误条件,最佳做法是创建自己的异常类。

@Michael There is actually one situation in which it is recommended to throw a NullReferenceException: If the first parameter (the "this" parameter) of an extension method is null. @Michael实际上有一种情况建议抛出NullReferenceException:如果扩展方法的第一个参数(“this”参数)为null。 You need to do this in order that null variables behave as expected. 您需要这样做才能使空变量按预期运行。

Microsoft was at one point telling programmers not to inherit directly from Exception, but instead to use ApplicationException as their base class. 微软曾经告诉程序员不要直接从Exception继承,而是使用ApplicationException作为他们的基类。 Not sure if that opinion still holds true, though... 不确定这个意见是否仍然适用,但......

And if a pre-defined exception already exists that covers your exact error condition (like "NullReferenceException", or "InvalidArgumentException" etc.) - by all means, throw those instead of re-inventing them inside your own code. 如果已经存在一个预定义的异常,它涵盖了你的确切错误条件(比如“NullReferenceException”或“InvalidArgumentException”等) - 无论如何,抛出这些异常而不是在你自己的代码中重新发明它们。

Marc

No one has posted a direct link to it, so here's the MSDN page with the complete list of Exception Do's and Don'ts没有人直接发布指向它的链接,所以这里是 MSDN 页面,其中包含异常注意事项的完整列表

https://learn.microsoft.com/en-us/do.net/standard/design-guidelines/using-standard-exception-types https://learn.microsoft.com/en-us/do.net/standard/design-guidelines/using-standard-exception-types

In terms of throwing the don'ts are...在投掷方面,注意事项是......

  • System.Exception系统异常
  • ApplicationException应用异常
  • NullReferenceException空引用异常
  • AccessViolationException访问冲突异常
  • IndexOutOfRangeException索引超出范围异常
  • StackOverflowException堆栈溢出异常
  • OutOfMemoryException内存不足异常
  • COMException异常
  • ExecutionEngineException执行引擎异常
  • SEHException SEH异常

It also has a list of don't catch and a recommendations on what exceptions you should throw它还有一个不要捕获的列表和关于你应该抛出哪些异常的建议

there are several exception already defined for you. 已经为您定义了几个例外。 Always try to use these Exceptions before roll your own 在推出自己的例外之前,请务必尝试使用这些例外

The online Design Guidelines for Exceptions contains the principle advice (see specifically this page). 在线例外设计指南中包含的原则意见(具体参见页)。

The book "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition" has more details and more discussion on this topic. “框架设计指南:可重用.NET库的约定,惯用法和模式,第2版”一书中有更多细节和有关该主题的更多讨论。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM