C# 在.NET中什么是ApplicationException?

C# 在.NET中什么是ApplicationException?,c#,.net,exception,exception-handling,C#,.net,Exception,Exception Handling,为了抛出异常,我通常使用内置的异常类,例如ArgumentNullException和NotSupportedException。但是,有时我需要使用自定义异常,在这种情况下,我编写: class SlippedOnABananaException : Exception { } class ChokedOnAnAppleException : Exception { } 等等。然后我在代码中抛出并捕获这些。但是今天我遇到了ApplicationException类-我应该使用它吗?这是干什么

为了抛出异常,我通常使用内置的异常类,例如
ArgumentNullException
NotSupportedException
。但是,有时我需要使用自定义异常,在这种情况下,我编写:

class SlippedOnABananaException : Exception { }
class ChokedOnAnAppleException : Exception { }
等等。然后我在代码中抛出并捕获这些。但是今天我遇到了
ApplicationException
类-我应该使用它吗?这是干什么用的

拥有大量具有不同名称的有效相同异常类(我通常不需要任何单独的功能)似乎效率低下。但是我不喜欢捕获一个通用的
ApplicationException
,并且必须使用额外的代码来确定错误是什么

根据msdn中的说明,
ApplicationException
应该在哪里与我的代码相匹配?

用户应用程序(而不是公共语言运行时)抛出从ApplicationException类派生的自定义异常。ApplicationException类区分应用程序定义的异常和系统定义的异常

如果设计的应用程序需要创建自己的异常,建议您从Exception类派生自定义异常。最初认为自定义异常应该派生自ApplicationException类;然而,在实践中,还没有发现这会增加显著的价值。有关更多信息,请参阅处理异常的最佳实践


异常
派生它们。此外,我不认为为您的案例创建新的异常有问题,只要它是有保证的。如果您遇到框架中已经存在异常的情况,请使用该异常,否则,请自行启动。

在最初的设计中,在.NET 1.0中,计划框架本身将抛出
SystemException
并派生;而用户应用程序-将抛出
ApplicationException
并派生

但后来,在.NET2.0中,这一点被放弃了


因此,从
异常

中得出的简短答案是:无处可去

它是过去的遗迹,微软希望开发人员从ApplicationException继承他们所有的自定义异常。不久之后,他们改变了主意,建议自定义异常应该从基异常类派生。请参阅MSDN上的

其中一个更广为传播的原因来自杰弗里·里希特(Jeffery Richter)在年的一次演习:

System.ApplicationException是一个不应属于.NET Framework的类。最初的想法是,从SystemException派生的类将指示从CLR(或系统)本身抛出的异常,而非CLR异常将从ApplicationException派生。然而,许多异常类并没有遵循这种模式。例如,TargetInvocationException(由CLR引发)是从ApplicationException派生的。因此,ApplicationException类失去了所有意义。从这个基类派生的原因是允许调用堆栈上更高的一些代码捕获基类。不再可能捕获所有应用程序异常


好了。执行摘要是ApplicationException不是有害的,只是无用的。

顺便说一句,从这个解释看来,这本身不是一个糟糕的设计,但MSFT把实现搞砸了。还有人读过类似的内容吗?@JoshKodroff:我认为问题在于,如果应用程序
Whizbang
决定将其所有异常都放在某个公共层次结构下,那么为此使用
ApplicationException
与使用自定义
whizbangeException
基类相比,实际上没有任何优势。然而,.net异常层次结构中更严重的问题不在于
ApplicationException
,而在于未能将异常划分为可能是应用程序致命的、可能是线程致命的和与本地问题相关的类别,以及无法进行有意义的“组合”异常。@JoshKodroff:在一个设计合理的异常框架中,IMHO,如果在另一个异常挂起时在
finally
块期间抛出异常,则如果调用堆栈上的
catch
块与任何嵌套异常匹配,则应触发调用堆栈上的
catch
块,但将其他异常保留为挂起状态,以便退出一个
catch
块将进入同一
try
块内的另一个
catch
块(如果有合适的话),如果退出一个
finally
块,而任何异常都将被挂起,则会跳转到下一个外部
catch
finally
@joshkodrof还有一件事我很惊讶没有得到更多的关注。“应用程序”到底是什么?第三方图书馆呢?因为它们不是.Net framework的一部分,所以它们应该按照最初的准则继承自ApplicationException。现在,当您在应用程序中使用该库并创建自己的ApplicationException时,您将无法再根据该库的异常识别自己的异常。所以这没用。相反,正如supercat所描述的,每个组件应该只定义它们自己的异常基类型。更重要的是,谁在乎异常是由CLR还是应用程序引发的呢?这不是一个有用的区别。
FileNotFoundException
在很大程度上是一个应该向用户报告的问题,但是是由CLR抛出的,而我自己的参数验证中的
ArgumentNullException
不是由CLR抛出的,但仍然意味着“程序员搞砸了”.Related:。因此,
ApplicationException
似乎是无用的,这仅仅是因为向后兼容吗?新的MSDN文档(至少4.7.2)忽略了这一点。谢谢你的qutoe:DDid他们试图在.NET核心重写中解决这个问题吗?