【问题标题】:Why can't control leave a finally statement?为什么不能控制留下finally语句?
【发布时间】:2026-02-20 14:40:02
【问题描述】:

当我在 finally 语句的块中放置 return 时,编译器会告诉我:

控件不能离开 finally 子句的主体

例子:

try
{
}
catch
{
}
finally
{
    return;
}

这是为什么?

【问题讨论】:

    标签: c# try-catch


    【解决方案1】:

    考虑一下如果你在try 块内return 1return 0finally 块内会发生什么...你的函数将试图返回两个值! trycatch 的组合选项在控制流方面是详尽无遗的。

    【讨论】:

    【解决方案2】:

    这是设计使然,并且在 C# 规范中有所描述:

    breakcontinuegoto 语句的编译时错误 将控制权转移出finally 块。当breakcontinuegoto 语句出现在 finally 块中,即语句的目标 必须在同一个 finally 块内,否则为编译时 发生错误。

    return 语句的编译时错误 发生在finally 块中

    另外,来自C# 6.0 spec draft on MSDN

    return 语句出现在 finally 块中是编译时错误。

    【讨论】:

    • 您的链接已失效,但我找不到新版本。
    • @ANeves 我也做不到。该规范随每个 Visual Studio 一起提供,因此报价仍然有效,只是链接无效。我在 C# 6.0 规范草案中添加了一个新的,具有相同的声明。
    【解决方案3】:

    当前的答案解释了为什么这种情况发生得很好,但我也认为重要的是要注意在不涉及返回值的情况下绕过这个约束是多么容易,并且finally 子句是最后一件事在方法中(经常发生):

    try {}
    catch {}
    finally
    {
        FinallyMethod();
    }
    

    然后在FinallyMethod 中,您可以随意使用return 语句

    void FinallyMethod()
    {
       //...
       if (x == y)
           return;
       else
           a = b;
       //etc.
    }
    

    【讨论】:

    • FinallyMethod 内部返回不会对包含 try/catch/finally 的方法执行任何操作。
    • 仅仅因为您来自FinallyMethodreturn 不会让您从调用站点返回。
    • 当然,但它对控制流很有用,例如if (!x) return; //do a lot of stuff。因此,您可以为此目的在 FinallyMethod 中使用 return,而不是在嵌套的 if 子句下执行所有操作。
    • 好的,我现在明白你的意思了。但这与问题中的示例并不真正相关,因为在使用示例时,您不会在finally 块中使用return
    • @Stijn 我同意这并不完全相关,只是提示,以防您方法中的最后一件事是 finally 子句(通常是这种情况),然后使用我建议的方法是相当于使用return。我已经在回答中澄清了这一点。