【问题标题】:Why finally block may not execute when exception is thrown?为什么抛出异常时finally块可能无法执行?
【发布时间】:2022-01-08 12:50:29
【问题描述】:

很长一段时间我都认为它可以让我释放finally块中的所有资源,我认为如果try块中发生异常,那么资源仍然会在try块中被释放finally 块。但似乎并非如此。

我有以下代码:

using System;

public sealed class Program
{

    public static void Main()
    {
        try {
            int zero = 0;
            int i = 1/zero;
        } finally {
            Console.WriteLine("divide by zero"); //the line is never called
        }
    }
}

我从来没有到达打印到控制台的行。这意味着在这种情况下,在try 块内引发异常时,我将无法释放finally 块中的资源。

所以,我相信有两件事:要么我遗漏了一些东西,要么try + finally 组合在 C# 中没有用例。第二个语句是有道理的,因为我将获得与上面代码相​​同的功能,下面的代码:

using System;

public sealed class Program
{

    public static void Main()
    {
            int zero = 0;
            int i = 1/zero;

            Console.WriteLine("divide by zero"); //the line is never called
    }
}

但我担心我可能会在这里遗漏一些东西。那么,有人可以确认该组合是无用的还是证明它没有用?

更新

在能够在其小提琴中调用finally 块的注释之后,我再次检查了VS Code,但仍然没有看到任何输出。

【问题讨论】:

  • @MichaelRandall 尝试使用 .NET Core 编译器:dotnetfiddle.net/8hLq8h
  • @JohnathanBarclay,哦。你是我的救命恩人。这是由于 .NET Core 的转换,而我习惯了 .NET Framework。非常感谢。
  • @JohnathanBarclay,我相信您的评论就是我一直在寻找的答案。能否请您将其添加为答案?
  • 这能回答你的问题吗? C# try catch confusion
  • @qqqqqqq Michael Randall 的回答解释了实际原因。我的小提琴只是一个观察。

标签: c# exception try-catch finally try-finally


【解决方案1】:

你的假设是不正确的(有时)https://dotnetfiddle.net/hjqmOS

try-finally (C# Reference)

通过使用 finally 块,您可以清理任何资源 在 try 块中分配,即使出现异常也可以运行代码 发生在 try 块中。通常,finally 块的语句 当控制离开 try 语句时运行。控制权转移可以 由于正常执行、执行中断而发生, continue、goto 或 return 语句,或异常传播 在 try 语句之外。

虽然有些情况下它不运行

在已处理的异常中,保证关联的 finally 块 要运行。 但是,如果异常未处理,则执行 finally 块取决于异常展开操作的方式 触发。反过来,这取决于您的计算机的设置方式。

这是重要的部分

通常,当未处理的异常结束应用程序时,无论是 不是 finally 块运行并不重要。 但是,如果您有 即使在这种情况下也必须运行的 finally 块中的语句, 一种解决方案是在 try-finally 语句中添加一个 catch 块。 或者,您可以捕获可能在 调用堆栈更高的 try-finally 语句的 try 块。

【讨论】:

  • 哇.. 不知道最后引用中的警告。似乎有点违反直觉……但话说回来,我认为我实际上并不需要阅读有关 try/catch 的文档(或者我是这么认为的!)。
  • @BrootsWaymb 令人惊讶的隐藏在那些讨厌的文档中:)
  • @MichaelRandall,这是否意味着.NET Core 支持最后一个文档引用,但.NET Framework 不支持?
  • @qqqqqqq 简而言之,使用catch-finally 处理异常以尝试确保运行。不要依赖环境
  • @MichaelRandall,明白了。谢谢你。请你也让我知道exception unwind operation triggering 是什么意思?我在文档中找不到任何解释这一点的东西。
【解决方案2】:

try/catch/finally 与释放资源无关。这是严格的应用程序流程和错误处理构造。您生活在托管代码中,垃圾收集器释放资源。此构造执行以下操作

try
{
    int zero = 0;
    int i = 1/zero;
}
catch (DividedByZeroException ex)
{
    Console.WriteLine(Exception handled);
    throw; // propagate ex to caller
}
finally
{
    Console.WriteLine("Method ended execution"); // called with or without exception
}

【讨论】:

  • @qqqqqqq 如果 T.S.投票赞成重复,另外两个投票赞成离题,这将计入 T.S. 对离题结束的投票。
  • @JonathonChase,哦。还有一条有用的信息。谢谢。
  • @T.S.,我很抱歉。看来我的指责是由于我缺乏知识而发生的。
  • @qqqqqqq 另外"Does this answer your question?"评论是系统自动添加到我的行为上的。
【解决方案3】:

我相信这是因为您有 VS 在未处理的错误上中断,因此 VS 会显示异常。如果您编译它并在命令行上手动运行它,我相信您会看到“除以零”。此外,您可以“处理”错误,而不是更改您的 VS 设置,然后应该会看到您期望的行为。

例子:

using System;

public sealed class Program
{

public static void Main()
{
    try
    {
        int zero = 0;
        int i = 1 / zero;
    }
    catch
    {

    }
    finally
    {
        Console.WriteLine("divide by zero"); 
    }
}
}

【讨论】:

  • 是的。我看到添加了 catch 块的输出。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-24
  • 2018-02-20
  • 1970-01-01
  • 2010-10-03
相关资源
最近更新 更多