try
{
try
{
throw new Exception("From Try");
}
catch
{
throw new Exception("From Catch");
}
finally
{
throw new Exception("From Finally");
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
上面代码的输出是:From Finally
。
为什么不是From Catch
?
-OR -
我怎样才能抓住&从外面登录两个例外?
答案 0 :(得分:6)
因为finally块在 catch块之后执行,所以覆盖异常。
当处理前一个异常时发生异常,第一个异常就会丢失。
我怎样才能抓住&从外面登录两个例外?
throw;
或将第一个异常作为新异常的InnerException传递。这就是InnerException
存在的原因。答案 1 :(得分:3)
这是C#语言规范定义的行为。对try
块中抛出的异常的处理将被中止,而finally
块中抛出的异常将被处理。
相关部分 8.9.5 throw语句解释了异常如何传播:
在当前函数成员中,将检查包含抛出点的每个
try
语句。对于每个语句S
,从最里面的try
语句开始,到最外面的try
语句结束,将评估以下步骤:
如果
S
的try块包含了抛出点且S
有一个或多个catch
子句,catch
子句将按顺序进行检查外观以找到异常的合适处理程序。指定异常类型的第一个catch
子句或异常类型的基本类型被视为匹配。一般catch
子句(§8.10
)被视为任何异常类型的匹配项。如果找到匹配的catch
子句,则通过将控制转移到该catch
子句的块来完成异常传播。否则,如果
try
块或catch
S
块包围投掷点且S
有一个finally块,则控制转移到最后一块。 如果finally
块抛出另一个异常,则终止当前异常的处理。否则,当控制到达finally
块的结束点时,处理当前异常是继续进行。
答案 2 :(得分:1)
添加一层额外的try-catch块,如下所示:
try {
Exception fromCatch = null;
try {
throw new Exception("From Try");
}
catch {
try {
throw new Exception("From Catch");
}
catch (Exception e) {
// catch failed -> store exception
fromCatch = e;
}
}
finally {
try {
throw new Exception("From Finally");
}
catch (Exception e) {
// i can think of better exception merging... but this shows the idea
throw new Exception(e.Message, fromCatch);
}
// throw fromCatch, in case "From Finally did not happen"
throw fromCatch;
}
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
if (ex.InnerException != null) {
Console.WriteLine(ex.InnerException.Message);
}
}
报告:
From Finally
From Catch
编辑:这显然是问题二的答案,因为“为什么”得到充分回答:)
答案 3 :(得分:0)
终于总是运行;它总是最后运行。因此,内部尝试完成的lat事件是最终的,并抛出了被外部捕获
捕获的东西不确定我是否理解问题的第2部分
答案 4 :(得分:0)
finally
无论如何都会发生。无论try或catch中是否存在异常。因此,您会看到“从最后”。 (这实际上是finally
子句的整个目的。所以你可以把代码放在那里,无论如何都会清理资源等 - 即使有异常。)
答案 5 :(得分:0)
您的代码会从try / catch / finally语句的每个部分抛出 new 异常。在创建新错误时,您基本上吞下了先前的异常。您可以使用
之类的内容将“From Try”消息添加到“From Catch”消息中catch(Exception ex)
{
throw new Exception(ex.Message + ":" + "From Catch");
}
我不知道你怎么能在终极中把它链接起来。
答案 6 :(得分:0)
因为finally块总是被执行。
try
{
try
{
throw new Exception("From Try");
// (1) A new exception object A is created here and thrown.
}
catch // (2) Exception object A is catched.
{
throw new Exception("From Catch");
// (3) A new exception object B is created here and thrown.
}
finally // (4) Execution is forced to continue here!
{
throw new Exception("From Finally");
// (5) A new exception object C is created here and thrown.
}
}
catch (Exception ex) // (6) Exception object C is catched.
{
Console.WriteLine(ex.Message);
}
步骤(3)和(5)中的每个新的异常对象都会丢弃前一个异常对象。由于始终执行finally块所有剩余的是来自步骤(5)的异常对象C.
答案 7 :(得分:0)
这是一个非常好的问题,而且有点棘手。让我们一步一步地完成这个过程:
try
{
throw new Exception("From Try");
}
catch
{
throw new Exception("From Catch");
}
在上面的代码中, Exception(“From Try”)被catch子句抛出并捕获(到目前为止非常简单)。 catch子句会抛出它自己的异常,通常我们会期望(因为catch嵌套在一个更大的try-catch块中)立即捕获,但是...
finally
{
throw new Exception("From Finally");
}
保证(尝试)执行的finally子句首先出现,并抛出它自己的异常,覆盖之前抛出的 Exception(“From Catch”)。 / p>
“catch的常见用法,最后 一起是获取和使用 处理try块中的资源 捕捞中的特殊情况 阻止,并释放资源 finally块“ - MSDN Article
遵循这一系列逻辑,我们应该尽力避免在我们的catch中编写代码,最后是容易出现异常的块。如果你担心像你提出的情况一样,我建议将异常及其相关信息记录到外部文件中,您可以参考该文件进行调试。