为什么在.NET中检查exception?
我知道谷歌search,我可以find一个合适的答案,但我更喜欢听你的个人(也许技术)的意见。
Java和C#在抛出exception方面有什么区别的主要原因是什么?
在Java中,引发exception的方法的签名必须使用“throws”关键字,而在C#中,如果可能抛出exception,则在编译期间不知道。
因为检查exception的响应几乎总是:
try { // exception throwing code } catch(Exception e) { // either log.error("Error fooing bar",e); // OR throw new RuntimeException(e); }
如果你真的知道,如果抛出一个特定的exception,你可以做什么,那么你可以捕捉它,然后处理它,但除此之外,这只是绥靖编译器的咒语。
在文章The Check with Exceptions和Anders Hejlsberg(C#语言的devise者)拥有自己的声音的文章中,有三个主要的原因让C#不支持被检查的exception,因为它们在Java中被发现和validation:
-
中立的检查例外
“C#在检查exception问题上基本保持沉默。 一旦有了更好的解决scheme,相信我们,我们会继续考虑,我们可以回去实际安排。“
-
版本检查exception
“在新版本中向throws子句添加新的exception会破坏客户端代码。 这就像添加一个方法到一个接口。 在你发布一个接口之后,对于所有实际的目的来说,它是不可变的,…“
“有趣的是,人们认为关于例外的重要事情是如何处理它们。 这不是关于例外的重要事情。 在一个写得很好的应用程序中,有一个十比一的比例,在我看来,尝试最终尝试抓住。 或者在C#中,
using
语句,就像最后一样尝试。“ -
检查exception的可伸缩性
“在小的情况下,检查的exception是非常诱人的…当你开始build立大型系统时,麻烦就开始了,在这个系统中你正在和四五个不同的子系统交谈。 每个子系统会抛出四到十个例外。 现在,每当你走上聚合的阶梯时,你就有必须处理的exception的指数层次。 你最终不得不宣布你可能抛出的40个例外……这只是无法控制的。
在他的文章中,“ 为什么C#没有exception规范? “, Anson Horton (Visual C#程序经理)也列出了以下原因(请参阅文章以获取关于每个点的详细信息):
- 版本
- 生产力和代码质量
- 让课堂作者区分已检查和未检查的例外是不切实际的
- 难以确定接口的正确例外。
有趣的是,C#确实支持通过<exception>
标记给定的方法抛出exception的文档,编译器甚至不费力地确认引用的exceptiontypes确实存在。 但是,在呼叫站点或使用该方法时没有进行检查。
您也可以查看“ 红帽软件”的商业工具Exception Hunter ,该工具使用静态分析来确定和报告由方法抛出的exception,并可能未被捕获:
例外猎人是一个新的分析工具,可以发现并报告你的function可能抛出的一系列可能的exception,甚至在你发货之前。 有了它,您可以轻松快速地find未处理的exception,直至引发exception的代码行。 一旦你有结果,你可以决定哪些exception需要处理(有一些exception处理代码),然后再把你的应用程序放到你的程序中。
最后, Thinking in Java的作者Bruce Eckel写了一篇文章叫做“ Java是否需要检查exception? “,这可能也值得一读,因为C#中为什么没有检查exception的问题通常在与Java比较中发挥作用。
C#的基本devise理念是实际捕获exception很less有用,而在特殊情况下清理资源非常重要。 我认为using
(IDisposable模式)是检查exception的答案是公平的。 参见[1]了解更多。
到.NETdevise时,Java已经检查了一段时间的exception,Java开发者充其量地看到了这个特性 争论的 有争议的 。 因此,.NETdevise人员select不将其包含在C#语言中。
从根本上说,是否应该处理exception是调用者的属性,而不是函数的属性。
例如,在某些程序中,处理IOException没有任何价值(考虑临时命令行实用程序执行数据处理;它们永远不会被“用户”使用,它们是专家人员使用的专家工具)。 在某些程序中,在接近调用点的地方处理一个IOException是有价值的(也许如果你的configuration文件得到一个FNFE,你将回到一些默认值,或者查看另一个位置,性质)。 在其他程序中,您希望它在处理之前冒出很长时间(例如,您可能希望在到达UI之前中止它,此时应该提醒用户出现了问题。
每种情况都取决于应用程序 ,而不是库 。 然而,经过检查的例外情况,这是决定的图书馆 。 在某些程序中,Java IO库决定使用检查的exception(强烈鼓励对本地调用进行处理),更好的策略可能是非本地处理,或根本不处理。
这显示了在实践中检查exception的真正缺陷,它比表面(虽然也是重要)缺陷更为根本,太多的人会编写愚蠢的exception处理程序,只是为了让编译器闭嘴。 即使经验丰富,有良心的开发人员编写程序,我所描述的问题也是一个问题。
有趣的是,微软研究院的研究人员增加了对Spec#的检查例外,他们是C#的超集。
安德斯自己在软件工程收音机播客的这一集中回答了这个问题
由于工作变化,我从Java转到了C#。 起初,我有点担心这种差异,但实际上并没有什么区别。
也许,这是因为我来自C ++,它有exception声明,但不常用。 我写每一行代码就好像它可以抛出一样 – 总是使用在Disposable周围,并考虑清理,我应该做的最后。
回想起Java中throws声明的传播并没有给我带来什么好处。
我想要一个方法来说,一个函数绝对不会抛出 – 我认为这将是更有用的。
除了已经写好的回答之外,没有检查过exception会在很多情况下帮助你很多。 检查exception使generics更难实现,如果您已经阅读了closuresbuild议,您会注意到每个closuresbuild议都必须以相当难看的方式绕过检查的exception。
我有时会错过在C#/ .NET中检查exception。
我想除了Java之外没有其他值得注意的平台有它们。 也许.NET的人刚刚走了stream…