如果我退出C#中的try/finally块,那么finally中的代码总会运行吗?

zor*_*org 18 c# try-catch-finally

它看起来像是根据一些初步测试,但我想知道的是,如果它保证返回或在某些情况下它不能返回?这对我的应用程序至关重要,但我还没有找到一个用例,但它不会返回.
我想获得有关该主题的专业知识.

Eri*_*ert 40

其他答案中有许多不准确之处.

当控制正常地离开try块时,控制被传递给finally块- 也就是说,通过返回,转到,中断,继续或者简单地从结束掉落.当控制通过一个被封闭的catch块捕获的异常离开try块时,控制被传递给finally .

在所有其他情况下,无法保证将调用finally块中的代码.特别是:

  • 如果try块代码进入无限循环,或者线程被冻结并且从未解冻,则永远不会调用finally块代码.

  • 如果进程在调试器中暂停然后被激活地终止,则从不调用finally块.如果进程执行失败快速,则永远不会调用finally块.

  • 如果将电源线拉出墙壁,则永远不会调用finally块.

  • 如果抛出没有相应catch块的异常,那么finally块是否运行是运行时的实现细节.当存在未捕获的异常时,运行时可以选择任何行为."不运行finally块"和"运行finally块"都是"任何行为"的示例,因此可以选择其中之一.通常,运行时所做的是询问用户是否要在finally块运行之前附加调试器; 如果用户说不,则finally块运行.但同样:运行时不需要这样做.它可能会快速失败.

你不能依赖于始终被调用的finally块.如果您需要强有力的保证代码执行,那么您不应该编写try-finally,您应该编写一个受约束的执行区域.正确编写CER是C#编程中最困难的任务之一,因此在尝试编写代码之前请仔细研究文档.

顺便提一下,关于最终封锁的getos的"有趣事实"是:

try { goto X; } finally { throw y; } 
X : Console.WriteLine("X");
Run Code Online (Sandbox Code Playgroud)

X是一个无法访问的标签,目标是可访问的goto!所以,下次你参加派对时,你可能会像"大家一样,任何人都可以制作一个C#程序,其中有一个无法访问的标签,目标是可访问的goto?" 你会看到在聚会上谁已经阅读了可达性规范,谁没有!

  • @Tergiver:鲜为人知的事实:编译器开发人员抛出最好的*派对. (13认同)
  • 故事的寓意是:永远不要邀请Eric Lippert参加你的派对;) (6认同)
  • @qqqqqq:但这才是真正令人讨厌的。假设您有 `void X() { try { GettingAdminPowers(); 做一些危险的事情();} 最后 { ReleaseAdminPowers(); }}` 和 `DoSomethingDangerous` 抛出异常。现在假设我们有 `try { X(); } catch (Exception) when (M()) { }}`。方法“M()”在管理权限释放之前运行!“X”的作者认为,除了“DoSomethingDangerous”之外,没有任何代码可以使用管理员权限,但作者错了! (3认同)

Dan*_*gby 21

无论try或catch块内发生了什么,finally块中的任何内容都将始终执行.如果您返回表单方法并不重要.

唯一的例外是,如果finally块中的代码抛出异常,那么它将像任何其他代码块一样停止执行.

关于goto,答案仍然是肯定的.请考虑以下代码:

try
{
    Console.WriteLine("Inside the Try");
    goto MyLabel;
}
finally
{
    Console.WriteLine("Inside the Finally");
}

MyLabel:
    Console.WriteLine("After the Label");
Run Code Online (Sandbox Code Playgroud)

产生的输出是这样的:

试试里面

在最后

标签之后


Luk*_*don 7

这里有些例子:

Environment.FailFast()

        try
        {
            Console.WriteLine("Try");
            Environment.FailFast("Test Fail");

        }
        catch (Exception)
        {
            Console.WriteLine("catch");
        }
        finally
        {
            Console.WriteLine("finally");
        }
Run Code Online (Sandbox Code Playgroud)

输出仅为“ Try”

堆栈溢出

        try
        {
            Console.WriteLine("Try");
            Rec();
        }
        catch (Exception)
        {
            Console.WriteLine("catch");
        }
        finally
        {
            Console.WriteLine("finally");
        }
Run Code Online (Sandbox Code Playgroud)

Rec在哪里:

    private static void Rec()
    {
        Rec();
    }
Run Code Online (Sandbox Code Playgroud)

输出仅为“ Try”,并且由于StackOverflow而终止了该过程。

未处理的异常

        try
        {
            Console.WriteLine("Try");
            throw new Exception();
        }
        finally
        {
            Console.WriteLine("finally");
        }
Run Code Online (Sandbox Code Playgroud)

  • 最后一个示例(**Unhanded exception**)实际上执行了“finally”块。 (2认同)