无论如何,我对何时传播异常以及何时包装它以及差异感到困惑.
目前,我的理解告诉我,包装异常将涉及像DriveNotFound(在IO中)之类的异常,然后使用常规IOException包装它.
但是,传播异常的概念,如果我有一个空的catch子句,这只会发生吗?因此,在ASP.NET Web应用程序中,它将传播到global.asax.或者在最近部署的Web应用程序的情况下,未处理的HTTPException给出了一个黄色的死亡屏幕,并写了一个日志到Windows Server(这是一个我正在重写的Web应用程序).因此异常发生在一个方法中,它可以在类级别处理,显示在页面中,然后上升到global.asax或Windows Server.
为什么我要用更通用的异常包装异常?规则是处理具有最特定类型的异常(因此DriveNotFound显然找不到驱动器).另外,我如何选择换行和替换异常?
异常处理链只是try和catch(或catches)子句吗?我从措词中假设,是的.
最后,为什么以及如何让异常在callstack上传播?
我确实阅读了有关异常处理的MS PandP指南,但我想这些示例并没有让我充分理解所有内容.
这个问题来自Enterprise Library包装/传播异常的能力等.这是我不确定的传播,以及替换/包装异常的差异.
此外,可以在catch块中插入复杂的错误处理逻辑(例如ifs/elses和类似的东西).
谢谢
Roa*_*ior 10
不少于6个问题:-)
但是,传播异常的概念,如果我有一个空的catch子句,这只会发生吗?
异常将向上传播,直到它被调用堆栈进一步向上捕获,该调用堆栈处理特定异常的类型或更接近该异常层次结构的基本类型的异常类型.因此,例如,所有托管异常都派生自System.Exception,因此拦截System.Exception的catch块将捕获每个托管异常.
为什么我要用更通用的异常包装异常?
我不确定你的意思是"换行".您是指捕获异常,将其替换为另一个异常,并将原始内容添加为新异常的InnerException属性?或者是其他东西?
我认为很少有理由用更通用的异常替换异常.但是,由于以下一个或多个原因,您当然可以用另一个例外替换异常:
另外,我如何选择换行和替换异常?
对不起,我仍然不明白你是如何将这两者定义为不同的.
异常处理链只是try和catch(或catches)子句吗?
以下是抛出异常时发生的基础知识:
CLR按顺序遍历本地Try ... End Try块中的Catch块列表,查找具有与抛出的异常匹配的异常过滤器的本地Catch块.
如果本地Catch块具有与抛出的确切异常匹配的异常过滤器,则执行该Catch块中的代码,然后执行Finally块中的代码.然后在结束尝试后的第一个语句处继续执行.
或者,如果抛出的异常派生自本地Catch块指定的异常,则会发生与第二步中所述相同的操作.例如,捕获ArgumentException的异常过滤器也将捕获从ArgumentException派生的异常,例如ArgumentNullException,InvalidEnumArgumentException,DuplicateWaitObjectException和ArgumentOutOfRangeException.
如果没有本地Catch块与抛出的异常匹配,则CLR按方法逐步返回调用堆栈,查找想要响应异常的Catch块.如果在调用堆栈中找不到匹配的Catch块,则认为该异常未处理.
或者,如果在调用堆栈的某处找到匹配的Catch块,则执行throw和catch之间的每个Finally块中的代码.这开始于属于Try块的Finally,其中抛出异常并在下面的方法中使用Finally捕获异常的方法结束.
对于捕获到异常的所有方法完成此清理后,控制权将转移到捕获异常的Catch块,并执行此代码.在运行旁边是Try的最后一个块,其中捕获了异常.现在调用堆栈已经解开并且错误清理已经完成,最后一步是在结束尝试之后的第一个语句处继续执行,其中捕获到异常.
如果Catch块中的代码导致抛出另一个异常,则使用InnerException属性将原始异常自动附加到新异常.通过这种方式,可以堆叠异常而不会丢失任何信息.
您应该避免将清理代码放在可能引发异常的Finally块中,除非该代码在其自己的Try块中.如果没有这种额外的保护,CLR的行为就好像在Finally块之后的结尾之后抛出了新的异常,并查找了想要响应新异常的远程Catch块的调用堆栈.除非原始Catch块保存,否则原始异常将丢失.
最后,为什么以及如何让异常在callstack上传播?
原因:每当您不明确了解异常并知道如何从中恢复时,您应该让它向上传播.
方法:仅捕获您理解并知道如何处理的异常类型.有时,您需要任何异常的详细信息才能进行适当的恢复.在这种情况下,您可以捕获它,执行恢复,然后使用throw重新抛出它; 声明.
此外,可以在catch块中插入复杂的错误处理逻辑(例如ifs/elses和类似的东西).
通常是的,因为由Catch块中的代码引起的任何新异常都会通过InnerException属性自动附加旧异常.但是,如果你可以避免它,那么激发这种机制是不明智的,所以你拥有的代码越简单越好.保持Catch代码简单的另一个好理由是它通常不会与主线代码进行相同程度的测试.
这一切都是为了向呼叫者传达正确的意义.我怀疑是否有理由将一个特定的异常包装在一个更通用的异常中 - 这对任何人都没有帮助.
考虑一个与文件访问无关但在后台访问配置文件的API.如果配置文件不存在,您可以将其包装在一起FileNotFoundException,ConfigurationException以便将正确的问题传达给呼叫者.
为什么以及如何让异常传播到callstack?
如果无法处理,则会传播异常.就这么简单.如果您的代码无法或应该做什么来解决异常,那么让它传播.传播时,要小心你这样做:
throw ex;
Run Code Online (Sandbox Code Playgroud)
不同于:
throw;
Run Code Online (Sandbox Code Playgroud)
前者抛弃旧的堆栈跟踪,并从抛出异常的点开始创建另一个.后者保留了原始堆栈跟踪.
当然,如果你无法处理异常,那么你可能不会在第一时间抓住它(也许你想记录).
| 归档时间: |
|
| 查看次数: |
2488 次 |
| 最近记录: |