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

时间:2008-09-23 21:52:25

标签: java .net exception

我知道谷歌搜索我可以找到合适的答案,但我更喜欢听你的个人(也许是技术)意见。
抛出异常时Java和C#之间差异的主要原因是什么?
在Java中,抛出异常的方法的签名必须使用“throws”关键字,而在C#中,如果可以抛出异常,则在编译时不知道。

10 个答案:

答案 0 :(得分:94)

在文章The Trouble with Checked Exceptions和Anders Hejlsberg(C#语言的设计者)自己的声音中,C#不支持检查异常有三个主要原因,因为它们是在Java中找到并验证的:

  • 已检查例外中性

      

    “C#基本上是无声的   例外问题。一旦更好   解决方案是已知的 - 并相信我们   继续思考它 - 我们可以去   回来,实际上放了一些东西   地方“。

  • 带已检查例外的版本控制

      

    “为投掷添加新例外   新版本中的子句打破了客户端   码。这就像添加方法一样   接口。发布后   界面,它是实用的   用途不可改变,......“

         人们认为这是多么有趣   关于例外的重要事情是   处理它们。那不是   关于例外的重要事情。在一个   写得很好的应用程序有一个   在我看来,比率是十比一   最后尝试捕捉。或者在C#中,   using语句   喜欢最后尝试。“

  • 已检查例外的可扩展性

      

    “在小的,经过检查的例外中   非常诱人...麻烦   当你开始建立大的时候就开始   与四个人交谈的系统   或五个不同的子系统。每   子系统抛出四到十个   例外。现在,每次你走了   聚合的阶梯,你有   你下面的这个指数层次结构   您必须处理的例外情况。   你最终不得不宣布40   你可能抛出的异常。...   它只是气球失控。“

在他的文章“Why doesn't C# have exception specifications?”中,Anson Horton(Visual C#项目经理)也列出了以下原因(有关每一点的详细信息,请参阅文章):

  • 版本
  • 生产力和代码质量
  • 让班级作者区分的不切实际 已选中未选中例外
  • 难以确定接口的正确异常。

有趣的是,C#确实支持通过<exception>标记由给定方法抛出的异常文档,编译器甚至会麻烦地验证引用的异常类型确实存在。但是,没有在呼叫站点进行检查或使用该方法。

您可能还想查看Exception Hunter这是Red Gate Software的商业工具,该工具使用静态分析来确定和报告方法抛出的异常,并且可能会被删除:< / p>

  

异常猎人是一种新的分析   找到并报告该组的工具   您的功能可能例外   可能会扔 - 在你发货之前。   有了它,你可以找到未处理的   容易和快速的例外,下至   抛出的代码行   例外。一旦你有了结果,   您可以决定需要哪些例外   待处理(有一些例外   处理代码)在你发布之前   应用到野外。

最后,Bruce Eckel的作者Thinking in Java有一篇名为“Does Java need Checked Exceptions?”的文章,可能值得一读,因为检查异常为何不存在的问题在C#中,通常在与Java的比较中扎根。

答案 1 :(得分:44)

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

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

如果您确实知道如果抛出特定异常就可以执行某些操作,那么您可以捕获它然后处理它,但除此之外,它只是安抚编译器的咒语。

答案 2 :(得分:13)

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

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

答案 3 :(得分:10)

在.NET设计时,Java已经检查了异常很长一段时间,Java开发人员最多只能将此功能视为 controversial controversial。因此.NET设计者chose不要将它包含在C#语言中。

答案 4 :(得分:8)

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

例如,在某些程序中,处理IOException没有任何价值(考虑使用ad hoc命令行实用程序来执行数据处理;它们永远不会被“用户”使用,它们是使用的专用工具由专业人士)。在某些程序中,在调用“接近”的位置处理IOException是有价值的(可能如果您获得配置文件的FNFE,您将退回到某些默认值,或查看其他位置,或者其他某个位置性质)。在其他程序中,您希望它在处理之前冒泡很长时间(例如,您可能希望它在中止到达UI之前中止,此时它应该警告用户出现了问题。

这些案例中的每一个都依赖于应用程序,而不是。然而,在检查过的例外情况下,正是做出了决定。 Java IO库决定它将使用已检查的异常(强烈鼓励处理呼叫的本地异常),而在某些程序中,更好的策略可能是非本地处理,或根本没有处理。

这显示了在实践中检查异常的真正缺陷,并且它比表面(虽然也很重要)的缺陷更为基础,因为太多人会编写愚蠢的异常处理程序只是为了让编译器闭嘴。即使经验丰富,尽职尽责的开发人员正在编写程序,我所描述的问题也是一个问题。

答案 5 :(得分:4)

有趣的是,微软研究院的人员已将检查过的例外添加到他们的C#超集Spec#中。

答案 6 :(得分:2)

Anders自己在软件工程广播播客的this episode中回答了这个问题

答案 7 :(得分:1)

由于工作变化,我从Java转到C#。起初,我有点担心这种差异,但在实践中,它没有什么不同。

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

回想起Java中throws声明的传播并没有给我带来任何好处。

我想说一个函数绝对不会抛出 - 我认为这会更有用。

答案 8 :(得分:1)

除了已经编写的回复之外,没有检查异常会在很多情况下帮助您。检查的异常使得泛型更难实现,如果您已经阅读了闭包建议,您会注意到每个闭包建议都必须以相当丑陋的方式处理已检查的异常。

答案 9 :(得分:1)

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

我认为除了Java之外没有其他值得注意的平台。也许.NET人员只是顺其自然......