.NET 中的 ApplicationException 是啥?
Posted
技术标签:
【中文标题】.NET 中的 ApplicationException 是啥?【英文标题】:What is ApplicationException for in .NET?.NET 中的 ApplicationException 是什么? 【发布时间】:2011-08-06 20:30:15 【问题描述】:为了抛出异常,我通常使用内置的异常类,例如ArgumentNullException
和 NotSupportedException
。但是,有时我需要使用自定义异常,在这种情况下我会写:
class SlippedOnABananaException : Exception
class ChokedOnAnAppleException : Exception
等等。然后我在我的代码中抛出并捕获这些。但是今天我遇到了ApplicationException
类——我应该改用它吗?有什么用?
拥有许多实际上相同但名称不同的异常类似乎效率低下(我通常不需要任何单独的功能)。但是我不喜欢捕获一个通用的ApplicationException
并不得不使用额外的代码来确定错误是什么的想法。
ApplicationException
应该在哪里适合我的代码?
【问题讨论】:
相关:***.com/questions/16603065/…. 【参考方案1】:根据msdn中的remarks:
用户应用程序,而不是公共语言运行时,会引发派生自 ApplicationException 类的自定义异常。 ApplicationException 类区分应用程序定义的异常和系统定义的异常。
如果您正在设计需要创建自己的异常的应用程序,建议您从 Exception 类派生自定义异常。最初认为自定义异常应该从 ApplicationException 类派生;然而在实践中,这并没有被发现可以增加显着的价值。有关详细信息,请参阅处理异常的最佳实践。
从Exception
派生它们。此外,只要有必要,我认为为您的案例创建新的例外没有问题。如果您遇到框架中已经存在异常的情况,请使用它,否则,请自行滚动。
【讨论】:
看来ApplicationException
没有用,仅仅是因为向后兼容吗?
新的 MSDN 文档,至少 4.7.2,错过了这句话。感谢您的报价:D
他们是否尝试在 .NET Core 重写中解决此问题?【参考方案2】:
在最初的设计中,在.NET 1.0中,计划框架本身会抛出SystemException
并派生;而用户应用程序 - 将抛出 ApplicationException
并派生。
但后来,在 .NET 2.0 中,它被删除了。
因此派生自Exception
。
【讨论】:
【参考方案3】:简短的回答是:无处。
这是过去的遗物,微软希望开发人员从 ApplicationException 继承所有自定义异常。不久之后,他们改变了主意,建议自定义异常应该从基类 Exception 派生。请参阅 MSDN 上的 Best Practices for Handling Exceptions。
其中一个更广为流传的原因来自 Jeffery Richter 在Framework Design Guidelines 中的一段摘录:
System.ApplicationException 是一个不应属于 .NET Framework 的类。最初的想法是,从 SystemException 派生的类将指示从 CLR(或系统)本身抛出的异常,而非 CLR 异常将从 ApplicationException 派生。然而,很多异常类并没有遵循这种模式。例如,TargetInvocationException(由 CLR 抛出)派生自 ApplicationException。因此,ApplicationException 类失去了所有意义。从这个基类派生的原因是允许调用堆栈更高的一些代码捕获基类。不再可能捕获所有应用程序异常。
所以你有它。执行摘要是 ApplicationException 没有有害,只是无用。
【讨论】:
顺便说一句,从这个解释看来,这本身并不是一个糟糕的设计,但 MSFT 搞砸了实现。其他人也读过类似的吗? @JoshKodroff:我认为问题在于,如果应用程序Whizbang
决定将其所有异常置于某个公共层次结构下,那么为此目的使用 ApplicationException
确实不会比使用自定义WhizbangException
基类。 .net 异常层次结构中更严重的问题不是ApplicationException
,而是未能将异常分为可能应用程序致命、可能线程致命和本地问题相关类别,以及无法有有意义的“复合”异常。
@JoshKodroff:恕我直言,在设计合理的异常框架中,如果在 finally
块期间抛出异常而另一个异常未决,catch
块进一步向上的调用堆栈应该被触发,如果它们匹配 any 嵌套异常,但保留其他异常待处理,以便退出 catch
块将继续到同一 try
块中的另一个 catch
块(如果有的话),并退出带有任何未决异常的 finally
块将跳转到下一个外部 catch
或 finally
。
@JoshKodroff 还有一件事我很惊讶没有得到更多关注。什么是真正的“应用程序”?那么第三方库呢?由于这些不是 .Net 框架的一部分,它们应该按照原始准则从 ApplicationException 继承。现在,当您在应用程序中使用该库并创建自己的 ApplicationExceptions 时,您将无法再根据此从库的异常中辨别出您自己的异常。所以没用。相反,每个组件都应该像 supercat 所描述的那样简单地定义自己的异常基类型。
更重要的是,谁在乎异常是由 CLR 还是应用程序抛出的?这不是一个有用的区别。 FileNotFoundException
是一个非常应该向用户报告的问题,但被 CLR 抛出,而我自己的参数验证中的 ArgumentNullException
不是由 CLR 抛出的,但仍然意味着“程序员搞砸了”。 以上是关于.NET 中的 ApplicationException 是啥?的主要内容,如果未能解决你的问题,请参考以下文章
.NET 中的 ApplicationException 是啥?