For a long time I thought that it allows me to free up all the resources in the finally block and I thought that if an exception happens in the try block, then the resources will still be free up in the finally block. But that seems not to be the case.
I have the following piece of code:
using System;
public sealed class Program
{
public static void Main()
{
try {
int zero = 0;
int i = 1/zero;
} finally {
Console.WriteLine("divide by zero"); //the line is never called
}
}
}
I never reach the line which prints to the console. That means that I will not be able to free up resource in finally block in this case on the exception being thrown inside the try block.
So, I believe there are two things: either I am missing something or the try + finally combination has no use cases in the C#. The second statement makes sense, because I will get the same functionality as is produced by the above code with the code below:
using System;
public sealed class Program
{
public static void Main()
{
int zero = 0;
int i = 1/zero;
Console.WriteLine("divide by zero"); //the line is never called
}
}
But I am afraid that I might be missing something here. So, could someone confirm that the combination is useless or prove that it is not, please?
UPDATE
After the comment which is able to call the finally block in its fiddle, I checked once more in the VS Code, and still I see no output.
You're assumptions are incorrect (sometimes) https://dotnetfiddle.net/hjqmOS
try-finally (C# Reference)
By using a finally block, you can clean up any resources that are
allocated in a try block, and you can run code even if an exception
occurs in the try block. Typically, the statements of a finally block
run when control leaves a try statement. The transfer of control can
occur as a result of normal execution, of execution of a break,
continue, goto, or return statement, or of propagation of an exception
out of the try statement.
There are cases when it doesn't run though
Within a handled exception, the associated finally block is guaranteed
to be run. However, if the exception is unhandled, execution of the
finally block is dependent on how the exception unwind operation is
triggered. That, in turn, is dependent on how your computer is set up.
Here is the important part
Usually, when an unhandled exception ends an application, whether or
not the finally block is run is not important. However, if you have
statements in a finally block that must be run even in that situation,
one solution is to add a catch block to the try-finally statement.
Alternatively, you can catch the exception that might be thrown in the
try block of a try-finally statement higher up the call stack.
try/catch/finally has nothing to do with freeing up resources. This is strictly application flow and error handling construct. You live in the managed code and garbage collector frees up resources. This construct does the following
try
{
int zero = 0;
int i = 1/zero;
}
catch (DividedByZeroException ex)
{
Console.WriteLine(Exception handled);
throw; // propagate ex to caller
}
finally
{
Console.WriteLine("Method ended execution"); // called with or without exception
}
I believe this is because you have VS to break on unhandled errors and thus VS steps in displaying the exception. If you compile it and run it manually on the command line I believe you will see "divide by zero". Also, instead of changing your VS settings, you can 'handle' the error and then should see the behavior you expect.
Example:
using System;
public sealed class Program
{
public static void Main()
{
try
{
int zero = 0;
int i = 1 / zero;
}
catch
{
}
finally
{
Console.WriteLine("divide by zero");
}
}
}
Related
We know that the code in the finally block is guaranteed to execute, regardless of whether the exception is caught. But let's say we have the following code:
class Program {
static void Main(string[] args) {
try {
int a = 0;
int b = 2021 / a;
}
finally {
System.Diagnostics.Debug.WriteLine("finally execute");
}
}
}
I cannot use Console.WriteLine since an unhandled exception terminates a process, no output written to the console, so I use System.Diagnostics.Debug.WriteLine, hopefully I can see "finally execute" displayed in the VS debug window.
When I execute the code, I didn't find "finally execute" in debug window, which means finally block won't execute if there is an unhandled exception.
If you look at this link https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/try-finally
It does say:
Part one
Within a handled exception, the associated finally block is guaranteed to be run. However, if the exception is unhandled, execution of the finally block is dependent on how the exception unwind operation is triggered. That, in turn, is dependent on how your computer is set up.
Part Two
The only cases where finally clauses don't run involve a program being immediately stopped. An example of this would be when InvalidProgramException gets thrown because of the IL statements being corrupt. On most operating systems, reasonable resource cleanup will take place as part of stopping and unloading the process.
My questions are:
Q1-What does "dependent on how your computer is set up" in Part One mean?
Q2-If it is dependent on how the computer is set up, then what does Part Two mean? The exception in my example is DivideByZeroException, not InvalidProgramException, so why the finllay block still doesn't execute
As per my understanding finally will execute in this case. As you have not use Catch block it throw unhandled exception to the process level so any statement after finally block will not execute.
This is the code.
using System;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args)
{
try
{
int a = 0;
int b = 2021 / a;
}
finally
{
Console.WriteLine("finally execute");
}
Console.WriteLine("Complete");
Console.ReadLine();
}
}
}
Sample output.
I've seen this example:
static void Main(string[] args)
{
Console.WriteLine("Start");
try
{
SomeOperation();
}
catch (Exception) when (EvaluatesTo())
{
Console.WriteLine("Catch");
}
finally
{
Console.WriteLine("Outer Finally");
}
}
private static bool EvaluatesTo()
{
Console.WriteLine($"EvaluatesTo: {Flag}");
return true;
}
private static void SomeOperation()
{
try
{
Flag = true;
throw new Exception("Boom");
}
finally
{
Flag = false;
Console.WriteLine("Inner Finally");
}
}
Which produces the next output:
Start
EvaluatesTo: True
Inner Finally
Catch
Outer Finally
This sounds weird to me, and I'm looking for a good explanation of this order to wrap it up in my head. I was expecting the finally block to be executed before when:
Start
Inner Finally
EvaluatesTo: True
Catch
Outer Finally
The documentation states that this execution order is correct, but it does not elaborate on why it is done like that and what exactly are the rules of the execution order here.
You might have been taught that when exception handling occurs, every method is considered separately. That is, since your inner method has a try...finally, any exception will first trigger the finally, and then it will "look" for a try higher up. This isn't true.
From the ECMA specification of CLR (ECMA-335, I.12.4.2.5 Overview of exception handling):
When an exception occurs, the CLI searches the array for the first protected block that
Protects a region including the current instruction pointer and
Is a catch handler block and
Whose filter wishes to handle the exception
If a match is not found in the current method, the calling method is searched, and so on. If no match is found the CLI will dump a stack trace and abort the program.
If a match is found, the CLI walks the stack back to the point just located, but this time calling the finally and fault handlers. It then starts the corresponding exception handler.
As you can see, the behaviour is 100% compliant with the specification.
Look for a protected block - try in SomeOperation
Does it have a catch handler block? No.
Look for a protected block in the calling method - try in Main
Does it have a catch handler block? Yes!
Does the filter wish to handle the exception? The filter is evaluated (disclaimer: this doesn't mean that all filters in the protected block will always be evaluated - no problem if the filter has no side-effects, which it really shouldn't, of course), and the result is yes.
Walk the stack back and execute all finally and fault handlers
finally in SomeOperation
The finally in Main isn't part of this, of course - it will execute when execution leaves the protected block, regardless of the exception.
EDIT:
Just for completeness - this has always been this way. The only thing that changed is that C# now supports exception filters, which allows you to observe the order of execution. VB.NET supported exception filters from version 1.
A finally block always executes whether or not an exception is thrown.
A finally block executes either:
After a catch block finishes
After control leaves the try block because of a jump statement (e.g., return or goto)
After the try block ends
The only things that can defeat a finally block are an infinite loop or the process sending abruptly. A finally block helps add determinism to a program
I don't have a problem; I'm just curious. Imagine the following scenario:
foreach (var foo in list)
{
try
{
//Some code
}
catch (Exception)
{
//Some more code
}
finally
{
continue;
}
}
This won't compile, as it raises compiler error CS0157:
Control cannot leave the body of a finally clause
Why?
finally blocks run whether an exception is thrown or not. If an exception is thrown, what the heck would continue do? You cannot continue execution of the loop, because an uncaught exception will transfer control to another function.
Even if no exception is thrown, finally will run when other control transfer statements inside the try/catch block run, like a return, for example, which brings the same problem.
In short, with the semantics of finally it doesn't make sense to allow transferring control from inside a finally block to the outside of it.
Supporting this with some alternative semantics would be more confusing than helpful, since there are simple workarounds that make the intended behaviour way clearer. So you get an error, and are forced to think properly about your problem. It's the general "throw you into the pit of success" idea that goes on in C#.
If you want to ignore exceptions (more often than not is a bad idea) and continue executing the loop, use a catch all block:
foreach ( var in list )
{
try{
//some code
}catch{
continue;
}
}
If you want to continue only when no uncaught exceptions are thrown, just put continue outside the try-block.
Here is a reliable source:
A continue statement cannot exit a finally block (Section 8.10). When
a continue statement occurs within a finally block, the target of the
continue statement must be within the same finally block; otherwise, a
compile-time error occurs.
It is taken from MSDN, 8.9.2 The continue statement.
The documentation say that:
The statements of a finally block are always executed when control leaves a
try statement. This is true whether the control transfer occurs as a
result of normal execution, as a result of executing a break,
continue, goto, or return statement, or as a result of propagating an
exception out of the try statement. If an exception is thrown during
execution of a finally block, the exception is propagated to the next
enclosing try statement. If another exception was in the process of
being propagated, that exception is lost. The process of propagating
an exception is discussed further in the description of the throw statement (Section 8.9.5).
It is from here 8.10 The try statement.
You may think it makes sense, but it doesn't make sense actually.
foreach (var v in List)
{
try
{
//Some code
}
catch (Exception)
{
//Some more code
break; or return;
}
finally
{
continue;
}
}
What do you intend to do a break or a continue when an exception is thrown? The C# compiler team doesn't want to make decision on their own by assuming break or continue. Instead, they decided to complain the developer situation will be ambiguous to transfer control from finally block.
So it is the job of developer to clearly state what he intends to do rather than compiler assuming something else.
I hope you understand why this doesn't compile!
As others have stated, but focused on exceptions, it's really about ambiguous handling of transferring control.
In your mind, you're probably thinking of a scenario like this:
public static object SafeMethod()
{
foreach(var item in list)
{
try
{
try
{
//do something that won't transfer control outside
}
catch
{
//catch everything to not throw exceptions
}
}
finally
{
if (someCondition)
//no exception will be thrown,
//so theoretically this could work
continue;
}
}
return someValue;
}
Theoretically, you can track the control flow and say, yes, this is "ok". No exception is thrown, no control is transferred. But the C# language designers had other issues in mind.
The Thrown Exception
public static void Exception()
{
try
{
foreach(var item in list)
{
try
{
throw new Exception("What now?");
}
finally
{
continue;
}
}
}
catch
{
//do I get hit?
}
}
The Dreaded Goto
public static void Goto()
{
foreach(var item in list)
{
try
{
goto pigsfly;
}
finally
{
continue;
}
}
pigsfly:
}
The Return
public static object ReturnSomething()
{
foreach(var item in list)
{
try
{
return item;
}
finally
{
continue;
}
}
}
The Breakup
public static void Break()
{
foreach(var item in list)
{
try
{
break;
}
finally
{
continue;
}
}
}
So in conclusion, yes, while there is a slight possibility of using a continue in situations where control isn't being transferred, but a good deal (majority?) of cases involve exceptions or return blocks. The language designers felt this would be too ambiguous and (likely) impossible to ensure at compile time that your continue is used only in cases where control flow is not being transferred.
In general continue does not make sense when used in finally block. Take a look at this:
foreach (var item in list)
{
try
{
throw new Exception();
}
finally{
//doesn't make sense as we are after exception
continue;
}
}
"This won't compile and I think it makes complete sense"
Well, I think it doesn't.
When you literally have catch(Exception) then you don't need the finally (and probably not even the continue).
When you have the more realistic catch(SomeException), what should happen when an exception is not caught? Your continue wants to go one way, the exception handling another.
You cannot leave the body of a finally block. This includes break, return and in your case continue keywords.
The finally block can be executed with an exception waiting to be rethrown. It wouldn't really make sense to be able to exit the block (by a continue or anything else) without rethrowing the exception.
If you want to continue your loop whatever happens, you do not need the finally statement: Just catch the exception and don't rethrow.
finally runs whether or not an uncaught exception is thrown. Others have already explained why this makes continue illogical, but here is an alternative that follows the spirit of what this code appears to be asking for. Basically, finally { continue; } is saying:
When there are caught exceptions, continue
When there are uncaught exceptions, allow them to be thrown, but still continue
(1) could be satisfied by placing continue at the end of each catch, and (2) could be satisfied by storing uncaught exceptions to be thrown later. You could write it like this:
var exceptions = new List<Exception>();
foreach (var foo in list) {
try {
// some code
} catch (InvalidOperationException ex) {
// handle specific exception
continue;
} catch (Exception ex) {
exceptions.Add(ex);
continue;
}
// some more code
}
if (exceptions.Any()) {
throw new AggregateException(exceptions);
}
Actually, finally would have also executed in the third case, where there were no exceptions thrown at all, caught or uncaught. If that was desired, you could of course just place a single continue after the try-catch block instead of inside each catch.
Technically speaking, it's a limitation of the underlying CIL. From the language spec:
Control transfer is never permitted to enter a catch handler or finally clause except through the exception handling mechanism.
and
Control transfer out of a protected region is only permitted through an exception instruction (leave, end.filter, end.catch, or end.finally)
On the doc page for the br instruction:
Control transfers into and out of try, catch, filter, and finally blocks cannot be performed by this instruction.
This last holds true for all branch instructions, including beq, brfalse, etc.
The designers of the language simply didn't want to (or couldn't) reason about the semantics of a finally block being terminated by a control transfer.
One issue, or perhaps the key issue, is that the finally block gets executed as part of some non-local control transfer (exception processing). The target of that control transfer isn't the enclosing loop; the exception processing aborts the loop and continues unwinding further.
If we have a control transfer out of the finally cleanup block, then the original control transfer is being "hijacked". It gets canceled, and control goes elsewhere.
The semantics can be worked out. Other languages have it.
The designers of C# decided to simply disallow static, "goto-like" control transfers, thereby simplifying things somewhat.
However, even if you do that, it doesn't solve the question of what happens if a dynamic transfer is initiated from a finally: what if the finally block calls a function, and that function throws? The original exception processing is then "hijacked".
If you work out the semantics of this second form of hijacking, there is no reason to banish the first type. They are really the same thing: a control transfer is a control transfer, whether it the same lexical scope or not.
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.
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!
Under normal conditions, code in a finally block will be executed regardless of what happens inside the try or catch blocks. It doesn't matter if you return from the method or not.
There are cases where this is not true. For example if the code in the finally block throws an exception, then it will stop executing like any other block of code.
Eric Lippert has written a much more comprehensive answer that outlines additional cases: https://stackoverflow.com/a/10260233/53777
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
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");
}
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.
I'm reviewing some code for a friend and say that he was using a return statement inside of a try-finally block. Does the code in the Finally section still fire even though the rest of the try block doesn't?
Example:
public bool someMethod()
{
try
{
return true;
throw new Exception("test"); // doesn't seem to get executed
}
finally
{
//code in question
}
}
Simple answer: Yes.
Normally, yes. The finally section is guaranteed to execute whatever happens including exceptions or return statement. An exception to this rule is an asynchronous exception happening on the thread (OutOfMemoryException, StackOverflowException).
To learn more about async exceptions and reliable code in that situations, read about constrained execution regions.
Here's a little test:
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");
}
}
}
The result is:
before
finally
return
after
Quoting from MSDN
finally is used to guarantee a statement block of code executes regardless of how the preceding try block is exited.
Generally yes, the finally will run.
For the following three scenarios, the finally will ALWAYS run:
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.
The following scenario, the finally will not run:
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.
Typically, unmanaged code is wrapped by some managed class before being consumed by user code. The managed wrapper class will typically make use of a SafeHandle to wrap the unmanaged handle. The SafeHandle implements a critical finalizer, and a Release method that is run in a CER to guarantee the execution of the clean-up code. For this reason, you should not see CERs littered through-out user code.
So the fact that the finally doesn't run on StackOverflowException should have no effect to user code, since the process will terminate anyway. If you have some edge case where you do need to clean-up some unmanaged resource, outside of a SafeHandle or CriticalFinalizerObject, then use a CER as follows; but please note, this is bad practice -- the unmanaged concept should be abstracted to a managed class(es) and appropriate SafeHandle(s) by design.
e.g.,
// 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.
}
There's a very important exception to this which I haven't seen mentioned in any other answers, and which (after programming in C# for 18 years) I can't believe I didn't know.
If you throw or trigger an exception of any sort inside your catch block (not just weird StackOverflowExceptions and things of that ilk), and you don't have the entire try/catch/finally block inside another try/catch block, your finally block won't execute. This is easily demonstrated - and if I hadn't seen it myself, given how often I've read that it's only really weird, tiny corner-cases that can cause a finally block not to execute, I wouldn't have believed it.
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();
}
I'm sure there's a reason for this, but it's bizarre that it's not more widely known. (It's noted here for instance, but not anywhere in this particular question.)
I realize I'm late to the party but in the scenario (differing from the OP's example) where indeed an exception is thrown MSDN states (https://msdn.microsoft.com/en-us/library/zwc8s4fz.aspx): "If the exception is not caught, execution of the finally block depends on whether the operating system chooses to trigger an exception unwind operation."
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.
Yes. That is in fact that main point of a finally statement. Unless something catestrophic occurs (out of memory, computer unplugged, etc.) the finally statement should always be executed.
It will also not fire on uncaught exception and running in a thread hosted in a Windows Service
Finally is not executed when in a Thread running in a Windows Service
finally wont run in case if you are exiting from the application using
System.exit(0); as in
try
{
System.out.println("try");
System.exit(0);
}
finally
{
System.out.println("finally");
}
the result would be just :
try
99% of the scenarios it will be guaranteed that the code inside the finally block will run, however, think of this scenario: You have a thread that has a try->finally block (no catch) and you get an unhandled exception within that thread. In this case, the thread will exit and its finally block will not be executed (the application can continue to run in this case)
This scenario is pretty rare, but it's only to show that the answer is not ALWAYS "Yes", it's most of the time "Yes" and sometimes, in rare conditions, "No".
The main purpose of finally block is to execute whatever is written inside it. It should not depend upon whatever happens in try or catch.However with System.Environment.Exit(1) the application will exit without moving to next line of code.