djn*_*jna 12 c# exception-handling
免责声明,我来自Java背景.我没有做太多的C#.这两个世界之间存在大量的转移,但当然存在差异,其中一个是异常倾向于被考虑的方式.
我最近回答了一个C#问题,建议在某些情况下,这样做是合理的:
try {
some work
} catch (Exeption e) {
commonExceptionHandler();
}
Run Code Online (Sandbox Code Playgroud)
(原因不重要).我收到的答复我不太明白:
直到.NET 4.0,捕获异常非常糟糕.这意味着你可以捕获各种低级致命错误,从而掩盖错误.它还意味着如果某种类型的损坏触发了这样的异常,堆栈上的任何打开的finally块都将被执行,所以即使callExceptionReporter函数尝试记录并退出,它甚至可能无法到达那一点( finally块可能再次抛出,或导致更多损坏,或从磁盘或数据库中删除重要的东西).
我可能比我意识到的更困惑,但我不同意其中的一些.请其他人评论.
我知道有很多低级别的例外我们不想接受.我的commonExceptionHandler()函数可以合理地重新抛出那些.这似乎与对相关问题的答案一致.这说"根据你的上下文,使用catch(...)是可以接受的,只要重新抛出异常即可." 所以我总结使用catch(Exception)并不总是邪恶,默默地吞下某些例外.
短语"在.NET 4之前它对Catch Exception来说非常糟糕".NET 4中有哪些变化?这是对AggregateException的引用,它可能会给我们一些与我们捕获的异常有关的新事物,但我不认为更改是基本的"不要吞下"规则.
下一句话真的很麻烦.这可能是对的吗?
它还意味着如果某种类型的损坏触发了这样的异常,堆栈上的任何打开的finally块都将被执行(finally块可能再次抛出,或导致更多损坏,或从磁盘或数据库中删除重要的东西)
我的理解是,如果有一些低级代码
lowLevelMethod() {
try {
lowestLevelMethod();
} finally {
some really important stuff
}
}
Run Code Online (Sandbox Code Playgroud)
在我的代码中我调用lowLevel();
try {
lowLevel()
} catch (Exception e) {
exception handling and maybe rethrowing
}
Run Code Online (Sandbox Code Playgroud)
无论我是否捕获异常,这对于finally块的执行都没有任何影响.当我们离开lowLevelMethod()时,finally已经运行了.如果最终要做任何坏事,比如我的磁盘损坏,那么它会这样做.我捕捉异常没有任何区别.如果它到达我的异常块我需要做正确的事情,但我不能成为dmis执行最终的原因
Ali*_*kau 11
对于问题#2:作者的意思是"腐败的国家例外".它们将在.NET 4.0中引入(CLR团队在本次演讲中在PDC 2008上宣布了这一点).
正常的catch块无法捕获损坏的状态异常.示例:访问冲突,无效内存.
但您可能想要捕获这些异常:
为此,您应该将属性[HandleProcessCorruptedStateException]放在要捕获CorruptedStateException的方法上.
要阅读有关这些异常的更多信息,请参阅此 MSDN文章.
作为一般规则,您不应该捕获异常,除非:
您有一个特定的例外,您可以处理和执行某些操作.但是,在这种情况下,您应该始终检查您是否应该首先考虑并避免例外.
您位于应用程序的顶层(例如UI),并且不希望将默认行为呈现给用户.例如,您可能需要一个带有"请发送给我们您的日志"样式消息的错误对话框.
在以某种方式处理异常后重新抛出异常,例如,如果您回滚数据库事务.
你的finally
块总是执行.你的代码示例是正确的 - 低级方法应该只有try
和finally
.例如,非托管调用可能知道它需要处理非托管资源,但这不会暴露给调用它的.Net方法.该调用应该摆脱其finally
块中的非托管资源,并且调用托管方法可以处理异常或只是将它们传递给它们.
如果您需要处理异常中的某些内容,则应重新抛出异常,例如:
try {
conn.BeginTransaction();
//do stuff
conn.CommitTransaction();
}
catch (Exception) {
conn.RollbackTransaction(); //required action on any exception
throw; //re-throw, don't wrap a new ex to keep the stack trace
}
finally {
conn.Dispose(); //always dispose of the resource
}
Run Code Online (Sandbox Code Playgroud)
我的座右铭是处理您可以(或需要)的内容,并让任何其他异常冒泡并在UnhandledException事件中捕获它们.
你是正确的,在退出方法之前总是调用finally块(即使在try部分引发异常的情况下).所以你是否想要在out方法上捕获异常完全取决于你.....这不应该影响被调用的finally块.