5

Let's say I have to catch 3 different exceptions, so I write 3 separate catch blocks. But I want to skip the finally block for one specific exception.

As far as I know this is not possible using a builtin flag. But can you advise how to solve this coding problem in elegant way?

When not using finally, I have to rewrite the same code several times, in try and also in other catch blocks.

More information: In finally I let the thread sleep for some time (await Task.Delay(5 * 1000);) But if I receive a OperationCanceledExceptionthen I don't want the finally to be run. I want it to break as fast as possible.

while (true)
{
    try
    {
        _cts.Token.ThrowIfCancellationRequested();
    }
    catch (OperationCanceledException)
    {
        break;
    }
    catch (CustomException1 e)
    {

    }
    catch (CustomException2 e)
    {

    }                
    finally
    {
        await Task.Delay(5 * 1000);
    }
}
Ozkan
  • 3,880
  • 9
  • 47
  • 78
  • 10
    Don't use finally then – Tim Schmelter May 24 '17 at 10:24
  • 5
    Make a bool outside the catch blocks, set it false. Then in your special catch block set it true and in finally check for the bool. Don't see why you would do this though – EpicKip May 24 '17 at 10:25
  • I agree with Tim, you are trying to avoid using the sole purpose of finally so makes sense not to use it. https://stackoverflow.com/questions/13545230/c-sharp-how-does-the-try-catch-finally-block-work Only solution I can think of is within the finally block have something like a if statement on a certain expect and return a particaular result from there. – Phil3992 May 24 '17 at 10:25
  • maybe you're trying to ask something else? because the current state of the question doesn't make sense. – Ovidiu Dolha May 24 '17 at 10:27
  • `finally` is intended to *allways* run, regardless on an exception (and some specific edge-cases that can´t be handled by a `catch` like a `StackOverflowException`). Taking one specific case out of this will break the while concept of finally. – MakePeaceGreatAgain May 24 '17 at 10:28
  • Comment from @EpicKip should be the answer IMO. However, it looks more like a big multi-responsibility try-catch problem that can be avoided with smaller specialized try-catch blocks – grek40 May 24 '17 at 10:28
  • 2
    It sounds like "one of these things is not like the others" - it may be possible to solve this by nesting two `try`/`catch` blocks where only one has a `finally`, but which way around this would need to be, and indeed whether this strategy would work very much depends on the specifics of the problem at hand. – Damien_The_Unbeliever May 24 '17 at 10:29
  • Also, check out [Polly](https://github.com/App-vNext/Polly). It's easy to say "retry on these conditions" (e.g., "delay and then retry when the exception is not `OperationCanceledException`). – Stephen Cleary May 24 '17 at 14:08

2 Answers2

10

Do nothing in the finally block if nothing is to be done

bool skipFinallyFlag = false;
try
{
    //My stuff
}
catch(Exception1 ex1)
{
    //Do something
}
catch(Exception2 ex2)
{
    //Do something
}
catch(Exception3 ex3)
{
    skipFinallyFlag = true;     
}
finally
{
    if(!skipFinallyFlag)
    {
        //Do something
    }
}
FortyTwo
  • 2,414
  • 3
  • 22
  • 33
1

Seems like you could use an exception-filter to filter all exceptions that should have some tidy-up-code and one single exception that doesn´t.

try
{
    DoSomething();
}
catch(Exception e) when (e is MyException || e is AnotherException)
{
    // your error-handling
    // ...
    await Task.Delay(5 * 1000);
}
catch(SpecificExceptionWithoutFinally e)
{
    ...
}

Before C#6 you could also introduce some flag indicating if the code should be executed:

var executeFinally = false;

try
{
    DoSomething();
}
catch(MyException e) 
{
    executeFinally = true;
}
catch(AnotherExceptione)
{
    executeFinally = true;
}    
catch(SpecificExceptionWithoutFinally e)
{
    ...
}
finally
{
    if(executeFinally) {
        await Task.Delay(5 * 1000);
    }
}

Anyway, this seems like a weird requirement, as the whole point of a finally is to be guaranteed to always run regardless on any exception being thrown.

MakePeaceGreatAgain
  • 35,491
  • 6
  • 60
  • 111