为什么在.NET中不检查异常?

时间:2020-03-06 14:37:48  来源:igfitidea点击:

我知道Google搜索可以找到合适的答案,但是我更喜欢听个人(也许是技术上的)意见。
Java和Cin抛出异常之间的区别的主要原因是什么?
在Java中,引发异常的方法的签名必须使用" throws"关键字,而在C中,我们在编译时不知道是否可以引发异常。

解决方案

实际上捕获异常的Cis的基本设计理念很少有用,而在异常情况下清理资源非常重要。我认为可以说" using"(IDisposable模式)是他们对已检查异常的答案。有关更多信息,请参见[1]。

  • http://www.artima.com/intv/handcuffs.html

因为对已检查异常的响应几乎总是:

try {
  // exception throwing code
} catch(Exception e) {
   // either
   log.error("Error fooing bar",e);
   // OR
   throw new RuntimeException(e);
}

如果我们确实知道如果抛出特定异常,我们可以执行某些操作,那么我们可以捕获该异常然后对其进行处理,但是否则,这只是使编译器安逸的咒语。

由于工作变动,我从Java转到了C。起初,我有点担心差异,但实际上,差异并没有。

也许是因为我来自C ++,它具有异常声明,但是并不常用。我写每一行代码,好像它可能会抛出一样-总是在Disposable周围使用use,并考虑最后应该做的清理。

回想一下,Java中throws声明的传播并没有真正让我有任何收获。

我想说一种函数绝对不会抛出的方法-我认为这样会更有用。

除了已经编写的响应之外,没有检查异常也可以在很多情况下为我们提供很多帮助。受检查的异常使泛型更难以实现,如果我们阅读了关闭建议,我们将注意到每个单独的关闭建议都必须以相当丑陋的方式解决受检查的异常。

在设计.NET时,Java已经检查了很长时间的异常,并且Java开发人员最多将此功能视为有争议的。因此,.NET设计人员选择不将其包括在Clanguage中。

有趣的是,Microsoft Research的人员已将检查异常添加到他们的C#超集Spec#中。

我有时会错过C#/。NET中的检查异常。

我想除了Java之外,没有其他著名的平台拥有它们。也许.NET家伙随波逐流...

在《检查异常的麻烦》一书中,以及在Anders Hejlsberg(语言的设计者)的心声中,Cnot支持在Java中找到并验证的异常的主要原因有三个:

  • 对检查的异常保持中性
“C# is basically silent on the checked
  exceptions issue. Once a better
  solution is known—and trust me we
  continue to think about it—we can go
  back and actually put something in
  place.”
  • 具有检查异常的版本控制
“Adding a new exception to a throws
  clause in a new version breaks client
  code. It's like adding a method to an
  interface. After you publish an
  interface, it is for all practical
  purposes immutable, …”
  
  “It is funny how people think that the
  important thing about exceptions    is
  handling them. That is not the
  important thing about exceptions. In a
  well-written application there's a
  ratio of ten to one, in my opinion, of
  try finally to try catch. Or in C#,
  using statements, which are
  like try finally.”
  • 检查异常的可伸缩性
“In the small, checked exceptions are
  very enticing…The trouble
  begins when you start building big
  systems where you're talking to four
  or five different subsystems. Each
  subsystem throws four to ten
  exceptions. Now, each time you walk up
  the ladder of aggregation, you have
  this exponential hierarchy below you
  of exceptions you have to deal with.
  You end up having to declare 40
  exceptions that you might throw.…
  It just balloons out of control.”

在他的文章"为什么Chave不提供异常规范?"中,Anson Horton(Visual CProgram Manager)还列出了以下原因(有关各点的详细信息,请参见文章):

  • 版本控制
  • 生产力和代码质量
  • 让类作者区分已检查异常和未检查异常是不切实际的
  • 难以确定接口的正确异常。

有趣的是,尽管如此,Cdoes通过<exception>标签支持给定方法抛出的异常的文档,并且编译器甚至费力地验证引用的异常类型确实存在。但是,没有在呼叫站点进行检查或者使用该方法。

我们可能还需要研究Exception Hunter,它是Red Gate Software的商业工具,它使用静态分析来确定和报告方法抛出的异常,并且可能无法捕获:

Exception Hunter is a new analysis
  tool that finds and reports the set of
  possible exceptions your functions
  might throw – before you even ship.
  With it, you can locate unhandled
  exceptions easily and quickly, down to
  the line of code that is throwing the
  exceptions. Once you have the results,
  you can decide which exceptions need
  to be handled (with some exception
  handling code) before you release your
  application into the wild.

最后,《 Thinking in Java》的作者Bruce Eckel发表了一篇文章,《 Java是否需要检查异常吗?》,这也值得一读,因为为什么Cusually中不存在检查异常的问题在与Java的比较中扎根了。

从根本上讲,是否应该处理异常是调用者的属性,而不是函数的属性。

例如,在某些程序中,处理IOException没有任何价值(请考虑使用临时命令行实用工具来执行数据处理;它们永远不会被"用户"使用,它们是专业人员使用的专家工具)。在某些程序中,在调用的"近端"处处理IOException是有价值的(也许,如果为配置文件获得FNFE,我们将放回某些默认值,或者查找其他位置,或者类似的东西自然)。在其他程序中,我们希望它在处理之前起泡很长时间(例如,我们可能希望它中止直到到达UI,这时它应该警告用户发生了问题。

这些情况中的每一种都取决于应用程序,而不是库。但是,除了已检查的异常外,是由库来做出决定的。当某些程序中更好的策略可能是非本地处理或者根本不处理时,Java IO库决定使用受检查的异常(强烈鼓励在调用本地处理)。

这显示了实践中检查异常的真正缺陷,它比表面上(尽管也很重要)缺陷更根本,因为太多人会编写愚蠢的异常处理程序只是为了使编译器关闭。即使有经验的,认真的开发人员正在编写程序,我描述的问题也是一个问题。

安德斯本人在本期软件工程电台播客中回答了这个问题