If I return out of a try/finally block in C# does the code in the finally always run?

*爱你&永不变心* 提交于 2019-11-27 01:36:21

问题


It seems like it does as per some initial testing, but what I'd like to know is if it is guaranteed to return or if in some cases it can not return? This is critical for my application but I haven't found a use-case yet where it wouldn't return.
I'd like to get expertise on the subject.


回答1:


Anything in a finally block will always be executed regardless of what happens inside the try or catch blocks. It doesn't matter if you return form the method or not.

The only exception to this is if the code in the finally block throws an exception, then it will stop executing like any other block of code.

In regards to goto, the answer is still yes. Consider the following code:

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

MyLabel:
    Console.WriteLine("After the Label");

The output produced is this:

Inside the Try

Inside the Finally

After the Label




回答2:


There are a number of inaccuracies in the other answers.

Control is passed to the finally block when control leaves the try block normally -- that is, by a return, goto, break, continue, or simply falling off the end. Control is passed to the finally block when control leaves the try block via an exception that has been caught by an enclosing catch block.

In every other circumstance there is no guarantee that the code in the finally block will be called. In particular:

  • If the try block code goes into an infinite loop, or the thread is frozen and never unfrozen, then the finally block code is never called.

  • If the process is paused in the debugger and then aggressively killed then the finally block is never called. If the process does a fail-fast then the finally block is never called.

  • If the power cord is pulled out of the wall then the finally block is never called.

  • If there is an exception thrown without a corresponding catch block then whether the finally block runs or not is an implementation detail of the runtime. The runtime can choose any behaviour when there is an uncaught exception. Both "do not run the finally blocks" and "do run the finally blocks" are examples of "any behaviour", so either can be chosen. Typically what the runtime does is ask the user if they want to attach a debugger before the finally blocks run; if the user says no then the finally blocks run. But again: the runtime is not required to do that. It could just fail fast.

You cannot rely on finally blocks always being called. If you require a strong guarantee about code executing then you should not be writing a try-finally, you should be writing a constrained execution region. Writing a CER correctly is one of the most difficult tasks in C# programming, so study the documentation carefully before you try to write the code.

Incidentally, a "fun fact" about finally-blocked gotos is:

try { goto X; } finally { throw y; } 
X : Console.WriteLine("X");

X is an unreachable label targetted by a reachable goto! So next time you're at a party you can be like "hey everybody, can anyone make a C# program that has an unreachable label that is targetted by a reachable goto?" and you'll see who at the party has read the reachability specification and who has not!




回答3:


Here are some examples:

Environment.FailFast()

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

        }
        catch (Exception)
        {
            Console.WriteLine("catch");
        }
        finally
        {
            Console.WriteLine("finally");
        }

The output is only "Try"

Stackoverflow

        try
        {
            Console.WriteLine("Try");
            Rec();
        }
        catch (Exception)
        {
            Console.WriteLine("catch");
        }
        finally
        {
            Console.WriteLine("finally");
        }

Where Rec is:

    private static void Rec()
    {
        Rec();
    }

The output is only "Try" and the process terminates due to StackOverflow.

Unhanded exception

        try
        {
            Console.WriteLine("Try");
            throw new Exception();
        }
        finally
        {
            Console.WriteLine("finally");
        }



回答4:


In case of fatal exceptions that terminate application Finally block will not be called. Includes stack overflow, exceptions during JIT of methods to call, fatal exceptions insisde CLR runtime.

As @mintech points out if application hangs inside the block it simply will not reach finally block. This includes waiting for synchronization objects, deadlocks infinite loops or even UI that does not have a way to close it.



来源:https://stackoverflow.com/questions/10255774/if-i-return-out-of-a-try-finally-block-in-c-sharp-does-the-code-in-the-finally-a

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!