Mar*_* Ba 4 .net language-design exception
初步说明:
这个问题不打算用于破坏.NET,也不打算讨论战争,如果存在"致命异常"这样的事情--Java的设计者清楚地认为存在,.NET设计者要么不这么认为,不知道否则,或者可能存在异常层次结构的另一个(技术)原因.
我最感兴趣的是,是否有任何MS设计人员的设计文档或声明,为什么.NET层次结构就像今天这样.疯狂的猜测和猜测会得到不好的答案.一致的论点/例子为什么没有这样的事情(可分类的)致命异常当然可以得到有效的答案,尽管我一定会不同意它们.但是,与评论相反,我保证不会与任何有凝聚力的答案争论;-)另一类答案可以证明Java的Error类型分类是一个坏主意/在Java实践中不起作用,从而隐含地显示为什么.NET不需要它.:-)
在努力成为一名经验更丰富的C#程序员的过程中,我注意到在.NET异常层次结构中我认为相当奇怪(*)的东西:
所有抛出类型的基类是Exception(好吧,基本上无论如何).
具体而言,许多例外直接从推导出Exception和进一步分类成SystemException- >等似乎相当无意义有点任意的.
作为一个例子,对我来说特别奇怪SEHException的ExternalExpection是,SystemException当它真的看起来更像是一种崩溃和烧伤的错误时,它就是a -a is-a .
虽然在Java中没有过多的经验,但我发现Java与wrt的区别.该Error类型与"正常" Exception,使有很大的意义.当然可以讨论细节,但是.NET/ C#甚至没有尝试这种方法似乎很奇怪.
C#成名的Eric Lippert 在分类异常方面有一个很好的部分,我大多赞同这一点,这让我更加想知道为什么.NET甚至没有试图为"致命异常"提供一个桶.
通过"致命异常"我基本上提到了Lippert先生描述的相同概念:
致命的例外不是你的错,你不能阻止他们,你不能明智地清理它们....
注意:最重要的是,它们很可能也可能也不是您调用引发异常的操作的错误.
......他们几乎总是发生,因为这个过程深深地病了,并且即将摆脱痛苦.内存不足,线程中止等.抓住这些是绝对没有意义的,因为你的微不足道的用户代码所做的一切都无法解决问题.让你的"终极"块运行并希望最好.(或者,如果你真的很担心,快速失败并且不要让最后的块运行;在这一点上,它们可能会让事情变得更糟.但这是另一天的主题.)
我会注意到,对于某些致命异常来说,技术上就像任何其他异常一样.你应该能够在适当的时候捕获它 - 只是99%的代码根本不适合处理它们.
以Lipperts先生为例:假设我调用一个函数来打开一个可以引发各种异常的文件.如果我抓到其中任何一个,我想要做的就是报告打开文件失败,原因为X并继续正确.但是,如果打开一个文件引发一个ThreadAbortedException,则报告任何内容没有意义,因为文件打开操作失败,但是一些代码中止当前线程并在假设FileNotFoundException不同的情况下处理它在绝大多数情况下都有意义.
评论者似乎认为只有捕获网站才能真正判断某些内容是否"致命"而且之前的分类是否合适,但我强烈怀疑99%的用户代码永远不会希望得到一个很好的例外列表:
拿StackOverflowException(并且我确定还有更多)这是"只是"一个固定的SystemException ,它是硬连线致命的:
在.NET Framework 1.0和1.1中,您可以捕获StackOverflowException对象(例如,从无限递归中恢复).从.NET Framework 2.0开始,您无法使用try/catch块捕获StackOverflowException对象,并且默认情况下会终止相应的进程.
请注意,我不认为致命异常必须立即终止申请(相反).我要问的是,为什么.NET框架不会试图在异常的层次结构中表示"致命性",而设计者显然认为某些异常比其他异常更致命.
(*)"考虑相当奇怪" 实际上意味着我个人,在时间连续的这一点,发现.NET异常层次结构完全拙劣.
Eri*_*ert 14
首先让我说这对StackOverflow来说不是一个特别好的问题.它不是关于实际代码的特定技术问题,而是寻求设计文档 - 异地资源 - 或者为什么特定类层次结构的设计原因.两者都不适合SO.
也就是说,我可以在这里做一些观察.
我认为这是一个合理的假设:人人参与感到遗憾的存在SystemException和ApplicationException.当时将异常划分为两大类似乎是个好主意:"系统"本身产生的异常,以及系统用户创建的异常.但实际上,这不是一个有用的区别,因为您使用异常执行的操作是捕获它们,并且在什么情况下您要捕获(1)所有用户生成的异常或(2)所有系统生成的异常?没有任何情况可以想到.
这里说明的不是特定情况下的设计失败 - 虽然设计肯定不是很好 - 而是在单继承OOP中你只得到一次"继承支点",因为它是通常在微软打电话,一个糟糕的决定可以坚持你很长一段时间.
现在很容易说回想起来,我们应该使用其他一些支点.你注意到在我的文章中我根据它们被捕获的方式对异常进行了分类 - 没有捕获到致命的异常,因为捕获它们对你没有好处,因为它们实际上是调试辅助工具而没有被捕获,所以必须抓住烦恼的异常因为API设计不好,必须抓住外生异常,因为它们表明世界与你所希望的不同.看起来这里有一个更好的支点的可能性,异常类型表明它是否致命,并表明它是否需要是否被抓住 这当然不是唯一可能的支点,但似乎有道理.可以设计静态分析器(在编译器或第三方工具中),以验证是否正确捕获了异常.
这似乎特别合理,因为.NET当然有一些例外,它们实际上是超级致命的.您可以捕获堆栈溢出或线程中止,但系统会重新抛出它们.如果以某种方式在元数据中捕获它会很好.
作为一名语言设计师,虽然我会进一步回顾,但是说这里的根本问题是异常机制本身如果不被滥用就会过度劳累.
例如,为什么我们需要致命的例外才是例外?如果确实存在某些异常是致命的情况,并且实际情况是在某些罕见但至关重要的情况下,即使程序由于致命异常而停止运行,您也需要运行代码,那么该情况可能会升级到您希望语言中的语法捕获这些语义的级别.说一个try-fatality清理代码仅在非常不可能的致命故障情况下运行的块.也许这是一个好主意,也许不是,但重点是,这是一个关于在语言中使用功能来解决问题的想法 而不是将越来越多的语义堆积到似乎可能不适合它所有用途的机制上.
例如,为什么会出现"愚蠢"的例外情况?存在像"这个引用不允许为空,你是虚拟"或"你试图在关闭它之后写入文件,你是虚拟"的骨头异常的存在,实际上只是例外,因为它们是缺点,在第一种情况是类型系统,第二种情况是API设计.理想情况下,不存在任何骨头异常,因为首先不可能用语言表示坏程序.像代码契约这样的机制可以构建到语言中,以帮助确保在编译时捕获"愚蠢的"异常情况.也许,这可能是一个好主意,也可能不是,但重点是有机会在语言设计层面解决这个问题,
| 归档时间: |
|
| 查看次数: |
961 次 |
| 最近记录: |