Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A lot of catch blocks, but in all of them the same function

What if I had something like this:

try
{
   //work
}
catch (ArgumentNullException e)
{
   HandleNullException();
   Logger.log("ArgumentNullException " + e);
   DoSomething();
}
catch (SomeOtherException e)
{
   HandleSomeOtherException();
   Logger.log("SomeOtherException " + e);
   DoSomething();
}
catch (Exception e)
{
   HandleException();
   Logger.log("Exception " + e);
   DoSomething();
}

Now as we can see, I'm trying to handle exceptions for some different cases. BUT whenever an exception is raised, I'm always calling the method DoSomething() at the end. Is there a smarter way to call DoSomething() if there is an exception? If I added a finally block and called DoSomething() there, it would always be called, even when there is no exception. Any suggestions?

like image 288
silla Avatar asked Jan 12 '13 21:01

silla


People also ask

What happens if we have multiple catch blocks?

Java Catch Multiple Exceptions A try block can be followed by one or more catch blocks. Each catch block must contain a different exception handler. So, if you have to perform different tasks at the occurrence of different exceptions, use java multi-catch block.

Can multiple catch blocks be executed at the same time?

No, multiple catch blocks cannot be executed. Once first catch block is catched, it will not read the next block.

Can we have multiple catch blocks?

Yes, we can define one try block with multiple catch blocks in Java. Every try should and must be associated with at least one catch block.

Can I have multiple try catch in a function?

You cannot have multiple try blocks with a single catch block. Each try block must be followed by catch or finally.


4 Answers

If I added a finally block and called DoSomething() there, it would always be called, even when there is no exception.

What you are looking for is known in the CLI standard (partition IIA, chapter 18) as a fault handler. Although .NET implements them, the C# language does not directly support them. However, they can be emulated:

bool success = false;
try
{
    …
    success = true;
}
catch (…)
{
    …
}
…
finally
{
    if (!success)
    {
        DoSomething();
    }
}

Note that there is no need to set the flag inside every catch handler, as some answers here suggest. Simply negate the test, and you only need to set the flag once, at the end of the try block.

like image 64
stakx - no longer contributing Avatar answered Oct 19 '22 22:10

stakx - no longer contributing


You can use the following code which actually does remove redundancies.

try
{
    //work
}
catch (Exception e)
{
    Handle(e);
}

Where the Handle method is:

static void Handle(Exception e)
{
    var exceptionType = e.GetType();
    //Use an if/else block, or use a Dictionary<Type, Action>
    //to operate on your exception
    Logger.log(exceptionType + " " + e);
    DoSomething();
}
like image 20
Mir Avatar answered Oct 19 '22 23:10

Mir


What you are doing now is about as good as it gets.

If you need to call this function whenever an exception happens, but not otherwise, and you must have different code for handling different exceptions, than this is the best that can be done.

like image 24
Oded Avatar answered Oct 19 '22 23:10

Oded


Why not just:

try
{
    //work
}
catch (Exception e)
{
    if (e is ArgumentNullException)
      HandleNullException();
    else if (e is SomeOtherException)
      HandleSomeOtherException();
    else
      HandleException();
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

The type name logged will be the actual runtime type, so for example "IndexOutOfRangeException" may be logged instead of just "Exception" if you're in case three, but I see this as an improvement over what you have now.

Edit: Above code looks awful with the ifelse if logic checking on types. If we introduced polymorphism, it could be more beautiful:

try
{
    //work
}
catch (HandleableException e)
{
    e.Handle();  // this calls a **virtual** method, each override does what's relevant
    Logger.log(e.GetType().Name + " " + e);
    DoSomething();
}

Of course, if some of the Exception classes in question cannot be modified by us, it would be impossible to give them a Handle() method. The .Handle() could also be an extension method (instead of a virtual instance method), but then the type checking (ugly code) would have to be done inside that method. Then this becomes quite similar to Eve's answer.

like image 22
Jeppe Stig Nielsen Avatar answered Oct 19 '22 22:10

Jeppe Stig Nielsen