抛出逻辑

时间:2010-09-29 22:30:30

标签: c# .net exception-handling try-catch-finally try-finally

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 -

我怎样才能抓住&从外面登录两个例外?

8 个答案:

答案 0 :(得分:6)

因为finally块在 catch块之后执行,所以覆盖异常。

当处理前一个异常时发生异常,第一个异常就会丢失。

  

我怎样才能抓住&从外面登录两个例外?

  1. 通过投掷到finally块中。这总是一个坏主意。
  2. 如果要登录内部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中编写代码,最后是容易出现异常的块。如果你担心像你提出的情况一样,我建议将异常及其相关信息记录到外部文件中,您可以参考该文件进行调试。