C# 抛接逻辑

C# 抛接逻辑,c#,.net,exception-handling,try-catch-finally,try-finally,C#,.net,Exception Handling,Try Catch Finally,Try Finally,上述代码的输出为:From Finally 为什么它不是Catch中的 -或- 如何从外部捕获和记录这两个异常?最终始终运行;而且它总是跑在最后。因此,内部尝试所做的最后一件事是最后一件,它抛出了被外部捕获的东西 不确定我是否理解问题的第2部分最后不管发生什么。无论try或catch中是否存在异常。因此,您可以看到“来自最终”。(这实际上是finally子句的全部目的。因此,您可以将代码放在其中,无论发生什么情况,都可以清理资源之类的东西,即使存在异常。)因为finally块在catch块之后执

上述代码的输出为:
From Finally

为什么它不是Catch中的

-或-


如何从外部捕获和记录这两个异常?

最终始终运行;而且它总是跑在最后。因此,内部尝试所做的最后一件事是最后一件,它抛出了被外部捕获的东西


不确定我是否理解问题的第2部分

最后
不管发生什么。无论try或catch中是否存在异常。因此,您可以看到“来自最终”。(这实际上是
finally
子句的全部目的。因此,您可以将代码放在其中,无论发生什么情况,都可以清理资源之类的东西,即使存在异常。)

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

当在处理早期异常的过程中发生异常时,第一个异常将丢失

如何从外部捕获和记录这两个异常

  • 通过在最后一个区块内投掷。那总是个坏主意
  • 如果要登录内部catch块,请使用
    throw
    或将第一个异常作为新异常的InnerException传递。这就是
    InnerException
    存在的原因

  • 您的代码从try/catch/finally语句的每个部分抛出一个新的异常。在创建新错误时,您实际上是在吞咽以前的异常。您可以使用以下内容将“From Try”消息添加到“From Catch”消息中

    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);
    }
    

    我不知道如何在finally中链接它。

    因为finally块总是被执行的

    catch(Exception ex)
    {
        throw new Exception(ex.Message + ":" + "From Catch");
    }
    

    步骤(3)和(5)中的每个新异常对象都会丢弃上一个异常对象。由于始终执行finally块,因此所有剩余的是步骤(5)中的异常对象C。

    这是C语言规范定义的行为。在
    try
    块中抛出的异常的处理被中止,而在
    finally
    块中抛出的异常将被处理

    相关的第8.9.5节throw语句解释了异常是如何传播的:

    • 在当前函数成员中,将检查包含抛出点的每个
      try
      语句。对于每个语句
      S
      ,从最里面的
      try
      语句开始,到最外面的
      try
      语句结束,将计算以下步骤:

      • 如果
        S
        的try块包含抛出点,并且
        S
        具有一个或多个
        catch
        子句,则将按外观顺序检查
        catch
        子句,以找到适合异常的处理程序。指定异常类型或异常类型的基类型的第一个
        catch
        子句被视为匹配。一般
        catch
        子句(
        §8.10
        )被视为与任何异常类型相匹配。如果找到了匹配的
        catch
        子句,则通过将控制权转移到该
        catch
        子句的块来完成异常传播

      • 否则,如果
        try
        块或
        S
        catch
        块包含抛出点,并且如果
        S
        具有finally块,则控制权转移到finally块如果
        finally
        块抛出另一个异常,则终止当前异常的处理。
        否则,当控制到达
        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); 
    } 
    
    在上面的代码中,catch子句抛出并捕获异常(“fromtry”)(到目前为止非常简单)。catch子句抛出它自己的异常,通常我们希望(因为catch嵌套在一个更大的try-catch块中)立即捕获该异常,但是

    try
    {
        throw new Exception("From Try");
    }
    catch
    {
        throw new Exception("From Catch");
    }
    
    finally子句保证(尝试)执行,它位于第一位,并抛出它自己的异常,覆盖先前抛出的异常(“fromcatch”)

    “catch和finally的常用用法 一起是为了获得和使用 try块中的资源,处理 捕获物中的特殊情况 块,然后释放中的资源 “最后一块”——


    遵循这一系列逻辑,我们应该尽最大努力避免在catch和finally块中编写容易发生异常的代码。如果您担心出现类似您所介绍的情况,我建议将异常及其相关信息记录到外部文件中,您可以参考该文件进行调试。

    添加一层额外的try-catch块,如下所示:

    finally
    {
       throw new Exception("From Finally");
    }
    
    报告:

    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);
        }
    }
    

    编辑:这显然是第二个问题的答案,因为“为什么”已经得到了充分的回答:)

    棘手…期待着看到这个问题的答案。当然我不是在finally块中自己抛出异常,在finally块中释放资源时可以抛出异常,这是一种正常的行为,我想知道那里有一个异常,这与我想要“From Catch”异常没有冲突。@dxck,这不是那么正常。资源释放代码通常不应抛出。你有一个具体的例子吗?例如:写入临时文件失败是因为磁盘空间不足,然后在finally块中我想删除该文件,但失败是因为IO错误或有人弄乱了该文件(例如磁盘清理程序)。在临时文件成功打开后,您可以并且应该写入finally部分,以便它不会抛出。关闭不会抛出,在这些情况下也不会删除。如果临时文件写入网络共享,则网络不可用。写入和删除操作将失败。你不能保证这一点
    From Finally
    From Catch