我正在为一个朋友检查一些代码,并说他在try-finally块中使用了return语句。即使try块的其余部分没有触发,Finally部分中的代码仍然会触发吗?

例子:

public bool someMethod()
{
  try
  {
    return true;
    throw new Exception("test"); // doesn't seem to get executed
  }
  finally
  {
    //code in question
  }
}

当前回答

它也不会触发未捕获的异常,并运行在Windows服务托管的线程中

Finally在运行在Windows服务中的线程中不执行

其他回答

finally块的主要目的是执行写入其中的内容。它不应该取决于try或catch中发生的任何事情。但是使用System.Environment.Exit(1),应用程序将退出而不移动到下一行代码。

通常情况下,是的。finally部分保证执行发生的任何事情,包括异常或返回语句。该规则的异常是线程上发生的异步异常(OutOfMemoryException, StackOverflowException)。

要了解在这种情况下异步异常和可靠代码的更多信息,请阅读约束执行区域。

简单的回答:是的。

这里有一个小测试:

class Class1
{
    [STAThread]
    static void Main(string[] args)
    {
        Console.WriteLine("before");
        Console.WriteLine(test());
        Console.WriteLine("after");
    }

    static string test()
    {
        try
        {
            return "return";
        }
        finally
        {
            Console.WriteLine("finally");
        }
    }
}

结果是:

before
finally
return
after

通常是的,最终会运行。

对于以下三种情况,finally将始终运行:

No exceptions occur Synchronous exceptions (exceptions that occur in normal program flow). This includes CLS compliant exceptions that derive from System.Exception and non-CLS compliant exceptions, which do not derive from System.Exception. Non-CLS compliant exceptions are automatically wrapped by the RuntimeWrappedException. C# cannot throw non-CLS complaint exceptions, but languages such as C++ can. C# could be calling into code written in a language that can throw non-CLS compliant exceptions. Asynchronous ThreadAbortException As of .NET 2.0, a ThreadAbortException will no longer prevent a finally from running. ThreadAbortException is now hoisted to before or after the finally. The finally will always run and will not be interrupted by a thread abort, so long as the try was actually entered before the thread abort occurred.

下面的场景,最后将不会运行:

Asynchronous StackOverflowException. As of .NET 2.0 a stack overflow will cause the process to terminate. The finally will not be run, unless a further constraint is applied to make the finally a CER (Constrained Execution Region). CERs should not be used in general user code. They should only be used where it is critical that clean-up code always run -- after all the process is shutting down on stack overflow anyway and all managed objects will therefore be cleaned-up by default. Thus, the only place a CER should be relevant is for resources that are allocated outside of the process, e.g., unmanaged handles.

通常,非托管代码在被用户代码使用之前由某个托管类包装。托管包装器类通常会使用SafeHandle来包装非托管句柄。SafeHandle实现了一个关键的终结器和一个在CER中运行的Release方法,以保证清理代码的执行。出于这个原因,您不应该看到cer遍布整个用户代码。

因此,finally不运行在StackOverflowException上的事实应该对用户代码没有影响,因为进程无论如何都会终止。如果你有一些边缘情况,你确实需要清理一些非托管资源,在SafeHandle或CriticalFinalizerObject之外,然后使用CER如下所示;但请注意,这是一种糟糕的做法——非托管概念应该通过设计抽象为托管类和适当的安全句柄。

例如,

// No code can appear after this line, before the try
RuntimeHelpers.PrepareConstrainedRegions();
try
{ 
    // This is *NOT* a CER
}
finally
{
    // This is a CER; guaranteed to run, if the try was entered, 
    // even if a StackOverflowException occurs.
}