为什么不能从 finally 块的内部跳转到外部?

Why a jump cannot be made from the inside to the outside of a finally block?

为什么跳转(break, continue, goto, return) 不能从finally块的内部跳转到外部(通过 throw 除外)?

Can anyone explain the technical reason?

没有,因为没有技术原因。完全有可能设计出允许分支离开 finally 的语言语义,而其他语言也允许这样做。可能会有一些小困难,因为 IL 中分支出现位置的规则对于 try-protected 区域是不同的,但这些很容易管理。

C# 不允许这种行为,因为如果它有这种特性,语言会更糟。从 finally 分支出来是一种糟糕的编程习惯,应该被禁止。

这样想。如果 finally 是 运行 因为异常,那么劫持与该异常相关的控制流是个坏主意; finally 的延续应该是实现定义的行为,如果异常未处理,在这种情况下它可以做任何事情,或者它应该是处理异常的 catch 块。 "cancel" 一个 "in-flight" 异常的唯一方法是抛出另一个异常并允许它被处理。

如果 finally 不是 运行 因为异常,那么你可以把你想要的控制流放在 try-finally 块之后。

因此,允许 finally 分支出来是错误的或不必要的。由于不需要从 finally 分支出来,而且这样做永远都是一个坏主意,因此应该将其定为非法。

是的,如果您尝试在 finally 中 return,则会出现错误

CS0157 Control cannot leave the body of a finally clause

但除了埃里克的出色回答,我完全同意他的意见,还有一个解决方法可能:

void Main() {
    MyFunction();
}

void MyFunction()
{

    void FinalActions() // local function used in the finally block below
    {
        for (int i = 0; i < 100; i++)
        {
            if (i>10)
            {
                Console.WriteLine("more than 10 ... ending.");

                // this  RETURNS  from the local function and hence ends the finally block
                return;
            }
        }
    }

    // the try-catch-finally block where we're using FinalActions()...
    try {
        // whatever you want to do here
    }
    catch (Exception ex) {
        // whatever you want to do here
        Console.WriteLine(ex.ToString());
    }
    finally {
        FinalActions(); // just invoke it, the rest is done there
    }

}

Try it as .NET Fiddle

局部函数FinalActions()一旦i>10通过使用关键字return返回就结束——注意这段代码只是为了展示从技术上讲,你可以做什么,你不会这样编程(在 for 循环中你只会说 i <= 10)。

当然还有其他关键字

break, continue, goto

也允许 在本地函数 FinalActions() 的上下文中,尽管我不鼓励使用 goto.


注意:旧版本的 C# 编译器不支持本地函数,您必须使用当前版本。