为什么 .NET 中未签入异常?

2022-09-01 01:40:45

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


答案 1

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

  • 对已检查的异常保持中立

    “C# 在已检查的异常问题上基本上是无提示的。一旦知道了更好的解决方案——相信我,我们将继续考虑它——我们就可以回去,把一些东西放到位。

  • 具有已检查例外的版本控制

    “在新版本中向 throws 子句添加新异常会中断客户端代码。这就像向接口添加方法一样。发布接口后,它对于所有实际目的都是不可变的,...”

    “有趣的是,人们认为异常的重要之处在于处理它们。这不是关于例外的重要事情。在我看来,在一个写得很好的应用程序中,有一个十比一的比例,即尝试最终尝试捕获。或者在C#中,使用语句,这就像尝试最后一样。

  • 已检查异常的可伸缩性

    “在小的,检查的例外是非常诱人的...当你开始构建大型系统时,麻烦就开始了,你正在与四五个不同的子系统交谈。每个子系统会引发四到十个异常。现在,每次你走上聚合的阶梯时,你都有这个指数级的层次结构,你必须处理异常。您最终必须声明40个可能引发的异常。...它只是失控了。

在他的文章“为什么 C# 没有异常规范?”中,Anson Horton(Visual C# 项目经理)还列出了以下原因(有关每个要点的详细信息,请参阅文章):

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

有趣的是,C#仍然支持通过<exception>标记由给定方法引发的异常的文档,编译器甚至会费力地验证引用的异常类型确实存在。但是,在调用站点上没有进行检查或该方法的使用情况。

您可能还需要查看异常猎人,这是Red Gate Software的商业工具,它使用静态分析来确定和报告由方法引发的异常,并且可能未被捕获:

异常猎人是一种新的分析工具,可以在您发货之前查找并报告您的函数可能引发的一组可能的异常。有了它,您可以轻松快速地找到未处理的异常,直到引发异常的代码行。获得结果后,您可以决定在将应用程序发布到野外之前需要处理哪些异常(使用一些异常处理代码)。

最后,《Thinking in Java》一书的作者 Bruce Eckel 有一篇文章,名为“Java 需要检查异常吗?”,这篇文章可能也值得一读,因为为什么 C# 中没有检查的异常的问题通常在与 Java 的比较中扎根。


答案 2

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

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

如果你真的知道在抛出一个特定的异常时你可以做些什么,那么你可以抓住它,然后处理它,但除此之外,它只是安抚编译器的咒语。