我正在为一个朋友检查一些代码,并说他在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
  }
}

当前回答

我意识到我迟到了,但在确实抛出异常的场景(与OP的示例不同)中,MSDN声明(https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx):“如果没有捕获异常,finally块的执行取决于操作系统是否选择触发异常unwind操作。”

The finally block is only guaranteed to execute if some other function (such as Main) further up the call stack catches the exception. This detail is usually not a problem because all run time environments (CLR and OS) C# programs run on free most resources a process owns when it exits (file handles etc.). In some cases it may be crucial though: A database operation half underway which you want to commit resp. unwind; or some remote connection which may not be closed automatically by the OS and then blocks a server.

其他回答

我意识到我迟到了,但在确实抛出异常的场景(与OP的示例不同)中,MSDN声明(https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx):“如果没有捕获异常,finally块的执行取决于操作系统是否选择触发异常unwind操作。”

The finally block is only guaranteed to execute if some other function (such as Main) further up the call stack catches the exception. This detail is usually not a problem because all run time environments (CLR and OS) C# programs run on free most resources a process owns when it exits (file handles etc.). In some cases it may be crucial though: A database operation half underway which you want to commit resp. unwind; or some remote connection which may not be closed automatically by the OS and then blocks a server.

有一个非常重要的例外,我在其他任何答案中都没有看到过,而且(在用c#编程了18年之后)我不敢相信我不知道。

如果你在catch块中抛出或触发任何类型的异常(不仅仅是奇怪的stackoverflowexception和类似的东西),并且你没有在另一个try/catch块中包含整个try/catch/finally块,你的finally块将不会执行。这很容易证明-如果我没有自己看到它,考虑到我经常读到它只是非常奇怪的,微小的角落情况,可以导致finally块不执行,我不会相信它。

static void Main(string[] args)
{
    Console.WriteLine("Beginning demo of how finally clause doesn't get executed");
    try
    {
        Console.WriteLine("Inside try but before exception.");
        throw new Exception("Exception #1");
    }
    catch (Exception ex)
    {
        Console.WriteLine($"Inside catch for the exception '{ex.Message}' (before throwing another exception).");
        throw;
    }
    finally
    {
        Console.WriteLine("This never gets executed, and that seems very, very wrong.");
    }

    Console.WriteLine("This never gets executed, but I wasn't expecting it to."); 
    Console.ReadLine();
}

我相信这是有原因的,但奇怪的是,它并没有广为人知。(例如,这里提到了,但在这个特定的问题中没有提到。)

引用自MSDN

Finally用于保证执行语句代码块,而不管前面的try块是如何退出的。

99%的情况下,finally块内的代码将会运行,但是,想想这个场景:你有一个线程,它有一个try->finally块(没有catch),你在该线程中得到一个未处理的异常。在这种情况下,线程将退出,它的finally块将不会执行(在这种情况下,应用程序可以继续运行)。

这种情况非常罕见,但这只是为了表明答案并不总是“是”,大多数情况下是“是”,有时在极少数情况下是“否”。

是的。这实际上是最后一个陈述的主要观点。除非发生了一些灾难性的事情(内存不足,计算机拔插等),finally语句应该始终执行。