I don\'t have a problem; I\'m just curious. Imagine the following scenario:
foreach (var foo in list)
{
try
{
//Some code
}
catch (E
The finally
block can be executed with an exception waiting to be rethrown. It wouldn't really make sense to be able to exit the block (by a continue
or anything else) without rethrowing the exception.
If you want to continue your loop whatever happens, you do not need the finally statement: Just catch the exception and don't rethrow.
Technically speaking, it's a limitation of the underlying CIL. From the language spec:
Control transfer is never permitted to enter a catch handler or finally clause except through the exception handling mechanism.
and
Control transfer out of a protected region is only permitted through an exception instruction (
leave
,end.filter
,end.catch
, orend.finally
)
On the doc page for the br instruction:
Control transfers into and out of try, catch, filter, and finally blocks cannot be performed by this instruction.
This last holds true for all branch instructions, including beq
, brfalse
, etc.
"This won't compile and I think it makes complete sense"
Well, I think it doesn't.
When you literally have catch(Exception)
then you don't need the finally (and probably not even the continue
).
When you have the more realistic catch(SomeException)
, what should happen when an exception is not caught? Your continue
wants to go one way, the exception handling another.
In general continue
does not make sense when used in finally
block. Take a look at this:
foreach (var item in list)
{
try
{
throw new Exception();
}
finally{
//doesn't make sense as we are after exception
continue;
}
}
finally
blocks run whether an exception is thrown or not. If an exception is thrown, what the heck would continue
do? You cannot continue execution of the loop, because an uncaught exception will transfer control to another function.
Even if no exception is thrown, finally
will run when other control transfer statements inside the try/catch block run, like a return
, for example, which brings the same problem.
In short, with the semantics of finally
it doesn't make sense to allow transferring control from inside a finally
block to the outside of it.
Supporting this with some alternative semantics would be more confusing than helpful, since there are simple workarounds that make the intended behaviour way clearer. So you get an error, and are forced to think properly about your problem. It's the general "throw you into the pit of success" idea that goes on in C#.
If you want to ignore exceptions (more often than not is a bad idea) and continue executing the loop, use a catch all block:
foreach ( var in list )
{
try{
//some code
}catch{
continue;
}
}
If you want to continue
only when no uncaught exceptions are thrown, just put continue
outside the try-block.