In languages with try-catch-finally, is it somehow possible to perform an action for all exception-handlers?

StackOverflow https://stackoverflow.com/questions/5819503

Question

Is there any language that supports something like the below construct, or is there a good way to achieve this using the ubiquitous try-catch-finally?

try
{

} catch(Exception1 e)
  { .... }
  catch(Exception2 e)
  { .... }
  catch-finally
   {
      //Perform action, such as logging
   }
  finally
   {
     //This always occurs but I only want to log when an exception occurs.
   }

I understand this depends on the particular language, but is there some such support in Java, C#, C++, PHP etc?

Was it helpful?

Solution

Put a "global" try/catch in your main program or high-level method. This catches all exceptions that are not caught elsewhere.

try
{
     // Main method, or higher level method call
} 
catch (Exception ex)
{
     // Log exception here
}

Then, in your subordinate try/catch clauses, just handle your exceptions in the usual way, and then rethrow. The rethrown exception will bubble up to your main try/catch and be logged.

try
{
     // Do your thing
}
catch(SomeException ex)
{
     // Handle exception here

     // rethrow exception to logging handler 
     throw;
}

OTHER TIPS

I don't think so as the behaviour you describe can be easily modelled as:

boolean success = false;

try {
  ...
  success = true;
} catch (Exception_1 e) {
  ...
}
...
} catch (Exception_N e) {
  ...
} finally {
  if (success) {
    // your "finally"
  } else {
    // your "catch-finally"
  }
}

You can easily accomplish that in C#. A simple way would be to save the exception in your catch blocks, then in your finally block, log if the exception object is not null.

Exception ex;

try
{

}
catch (ExceptionType1 type1)
{
    ex = type1;
}
catch (ExceptionType2 type2)
{
    ex = type2;
}
finally
{
    if (ex != null)
    {
        //Log
    }
}

Visual Basic has a construct that can be used for this. This isn't really "finally" in the sense of [almost] never failing to execute, but it'll support the case when you only want to log the exceptions that you're handling, and you have access to the exception object within the shared code. You've also got the flexibility of having the shared code execute before or after the individual exception type code.

Try
    ...
Catch ex As Exception When TypeOf(ex) Is Type1 OrElse TypeOf(ex) Is Type2
    ...
    If TypeOf(ex) Is Type1 Then
        ...
    ElseIf TypeOf(ex) Is Type2 Then
        ...
    End If
End Try

Something like this, as long as the language has throw with no parameters to rethrow a caught exception:

try
{

} catch(Everything) {
    try {
        throw;
    } catch (Exception1 e) {
        ....
    } catch (Exception2 e) {
        ....
    } finally {
        //Perform action, such as logging
    }
} finally {
        //This always occurs but I only want to log when an exception occurs.
}

That's if you want to log whenever an exception occurs - if you only want to log the ones you actually catch, then don't put the "Perform action" in a finally block, just put it after the end of the inner try-catch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top