Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use case for try-catch-finally with both catch and finally

I understand how try-catch works and how try-finally works, but I find myself using those (usually) in two completely different scenarios:

  • try-finally (or using in C# and VB) is mostly used around some medium-sized code block that uses some resource that needs to be disposed properly.
  • try-catch is mostly used either
    • around a single statement that can fail in a very specific way or
    • (as a catch-all) at a very high level of the application, usually directly below some user interface action.

In my experience, cases where a try-catch-finally would be appropriate, i.e., where the block in which I want to catch some particular exception is exactly the same block in which I use some disposable resource, are extremely rare. Yet, the language designers of C#, VB and Java seem to consider this to be a highly common scenario; the VB designers even think about adding catch to using.

Am I missing something? Or am I just overly pedantic with my restrictive use of try-catch?


EDIT: To clarify: My code usually looks like this (functions unrolled for clarity):

Try
    do something
    Aquire Resource (e.g. get DB connection)
    Try 
        do something
        Try
            do something that can fail
        Catch SomeException
            handle expected error
        do something else... 
    Finally 
        Close Resource (e.g. close DB connection)
    do something
Catch all
    handle unexpected errors

which just seems to make much more sense than putting any of the two catches on the same level as finally just to avoid indentation.

like image 984
Heinzi Avatar asked Feb 17 '10 10:02

Heinzi


1 Answers

A quote from MSDN

A common usage of catch and finally together is to obtain and use resources in a try block, deal with exceptional circumstances in a catch block, and release the resources in the finally block.

So to make it even more clear, think of the code that you want to run, in 99% of the cases it runs perfectly well but somewhere in the chunk there might occure an error, you don't know where and the resources created are expensive.

In order to be 100% sure that the resources are disposed of, you use the finally block, however, you want to pin-point that 1% of cases where the error occures, therefore you might want to set up logging in the catch-ing-section.

That's a very common scenario.

Edit - A Practical Example

There is some good examples here: SQL Transactions with SqlTransaction Class. This is just one of the many ways to use Try, Catch & Finally and it demonstrates it very well, even though a using(var x = new SqlTranscation) might be efficient some times.

So here goes.

var connection = new SqlConnection();

var command = new SqlCommand();

var transaction = connection.BeginTransaction();

command.Connection = connection;
command.Transaction = transaction;

Here comes the more interesting parts

///
/// Try to drop a database
///
try
{
    connection.Open();

    command.CommandText = "drop database Nothwind";

    command.ExecuteNonQuery();
}

So let's imagine that the above fails for some reason and an exception is thrown

///
/// Due to insufficient priviligies we couldn't do it, an exception was thrown
///
catch(Exception ex)
{
    transaction.Rollback();
}

The transaction will be rolled back! Remember, changes you made to objects inside the try/catch will not be rolled back, not even if you nest it inside a using!

///
/// Clean up the resources
///
finally
{

    connection.Close();
    transaction = null;
    command = null;
    connection = null;
}

Now the resources are cleaned up!

like image 58
Filip Ekberg Avatar answered Nov 15 '22 21:11

Filip Ekberg