Why can't a 'continue' statement be inside a 'finally' block?

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#.

C#, you, and the out if success

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.


Here is a reliable source:

A continue statement cannot exit a finally block (Section 8.10). When a continue statement occurs within a finally block, the target of the continue statement must be within the same finally block; otherwise, a compile-time error occurs.

It is taken from MSDN, 8.9.2 The continue statement.

The documentation say that:

The statements of a finally block are always executed when control leaves a try statement. This is true whether the control transfer occurs as a result of normal execution, as a result of executing a break, continue, goto, or return statement, or as a result of propagating an exception out of the try statement. If an exception is thrown during execution of a finally block, the exception is propagated to the next enclosing try statement. If another exception was in the process of being propagated, that exception is lost. The process of propagating an exception is discussed further in the description of the throw statement (Section 8.9.5).

It is from here 8.10 The try statement.


You may think it makes sense, but it doesn't make sense actually.

foreach (var v in List)
{
    try
    {
        //Some code
    }
    catch (Exception)
    {
        //Some more code
        break; or return;
    }
    finally
    {
        continue;
    }
}

What do you intend to do a break or a continue when an exception is thrown? The C# compiler team doesn't want to make decision on their own by assuming break or continue. Instead, they decided to complain the developer situation will be ambiguous to transfer control from finally block.

So it is the job of developer to clearly state what he intends to do rather than compiler assuming something else.

I hope you understand why this doesn't compile!

Tags:

C#

.Net