I'm wondering if this code will work in the way that after 10 retries CleanUp()
will be called? Or will the throw new Exception()
not get caught by the last catch block?
public void Process()
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
catch (Exception e)
{
CleanUp();
}
}
CodePudding user response:
No, it doesn't work like that. For any given try
/catch
block, only an exception originating in the try
can be caught by the corresponding catch
blocks. Exceptions thrown within catch
blocks are not catchable by other catch
blocks at the same level.
finally
blocks allow you to run code when control leaves a try
/catch
for any reason. So if the end of your try
already has a CleanUp
then you would just change your final catch(Exception e)
to finally
and remove the CleanUp
at the end of the try
part.
If, however, you only want to run CleanUp
when control leaves the try
/catch
via an exception, you're not so lucky. There is a fault
clause in IL, which is finally
, but only for exceptions, but that's not exposed in C#.
So if you need that, it's usually best to introduce an extra bool
that indicates you reached the end of the try
block without exception, and use that to make your CleanUp
call conditional in the finally
.
Or you may simulate try
/catch
/fault
by nesting try
/catch
blocks:
try
{
try
{}
catch (MyException e)
{
int retries = GetRetries();
if(retries > 10)
{
_logger.LogError("Retried event already {retries} times. Giving up.", retries);
throw new Exception("Giving up!");
}
Process();
}
}
catch
{
//Act as fault
CleanUp();
throw;
}