Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the use of a finally block preceded by a catch-all catch block, in C#?

Consider the following C# code structure (S0-S3 are placeholders for arbitrary code blocks):

try
{
    S0;
}
catch (Exception ex)
{
    S1;
}
finally
{
    S2;
}

S3;

In the case that S1 throws an exception inside the catch handler, S2 inside the finally will still execute (but S3 will not).

Question

Assuming that S1 cannot throw, is there any point in having S2 inside a finally block, rather than having it outside the try/catch/finally, just before S3?

Example

try
{
    // Do something that might throw
}
catch (Exception ex)
{
    // Save the exception to re-throw later
    // NB: This statement cannot throw an exception!
    this.cachedException = ex;
}
finally
{
    S2;
}

S3;

Is there any point in having the finally block? Would the following code not be equivalent (under the strict assumption that what's inside the catch block cannot throw):

try
{
    // Do something that might throw
}
catch (Exception ex)
{
    // Save the exception to re-throw later
    // NB: This statement cannot throw an exception!
    this.cachedException = ex;
}

// No finally block needed (?)
S2;
S3;

Secondary Question

Update: If it is accepted that the two code blocks above are equivalent (under the assumptions stated) then, taking into account the feedback on code clarity in the answers, would it be preferrable (and equivalent) to combine S2 and S3 inside the finally block?

try
{
    // Do something that might throw
}
catch (Exception ex)
{
    // Save the exception to re-throw later
    // NB: This statement cannot throw an exception!
    this.cachedException = ex;
}
finally
{
    S2; // Put S2 and S3 together inside the `finally` block to guard against
    S3; // future changes in the `catch` filter, or handling code.
}
like image 640
Daniel Fortunov Avatar asked Jan 11 '10 12:01

Daniel Fortunov


People also ask

What is the purpose of a finally block in the try catch block?

A Finally block is useful for running any code that must execute even if there is an exception. Control is passed to the Finally block regardless of how the Try...Catch block exits. The code in a Finally block runs even if your code encounters a Return statement in a Try or Catch block.

What is the relationship between a catch block and a finally block?

Catch block contains the exception handler for exceptions in the try block. The finally block contains the critical code that will execute regardless of whether the exception has occurred or not.

Is a Finally block required after a catch block?

Finally block is optional, as we have seen in previous tutorials that a try-catch block is sufficient for exception handling, however if you place a finally block then it will always run after the execution of try block. 3.

What is the purpose of catch blocks?

Try/catch blocks allow a program to handle an exception gracefully in the way the programmer wants them to. For example, try/catch blocks will let a program print an error message (rather than simply crash) if it can't find an input file. Try blocks are the first part of try/catch blocks.


1 Answers

The assumption that S1 cannot throw is a fragile one, considering resource depletion scenarios (i.e., you run out of memory). Even if warranted (a big if), minor changes to the code can introduce an exception.

Since S2 is usually concerned with cleaning up and releasing valuable resources, putting it in a finally block communicates that intention clearly. Putting such code, where possible, in a Dispose() method of a resource owning object and replacing the try/finally clause with a using clause can communicate the intention even better (and more idiomatically for C#).

Whenever you can write something in two or more different ways, use the one that is clearest and most stable against changes.

Re the secondary question: S3 should be placed inside the finally if it's concerned with cleanup. If it presupposes the success of the try block, it should be placed after the finally block. If your catch statement doesn't rethrow, I personally would interpret it to mean that you have succeeded and can proceed with normal operations. However, the whole 'Save the exception to re-throw later' thing confuses me. Generally, I'd advise against storing an exception for rethrowing outside the method. It's unusual and seems confusing to me. The fewer surprises your code contains, the easier it is to maintain (including yourself, three months later).

like image 139
Pontus Gagge Avatar answered Nov 15 '22 17:11

Pontus Gagge