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

后端 未结 11 764
情深已故
情深已故 2020-12-23 02:38

I don\'t have a problem; I\'m just curious. Imagine the following scenario:

foreach (var foo in list)
{
    try
    {
         //Some code
    }
    catch (E         


        
相关标签:
11条回答
  • 2020-12-23 03:21

    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.

    0 讨论(0)
  • 2020-12-23 03:21

    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, or end.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.

    0 讨论(0)
  • 2020-12-23 03:24

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

    0 讨论(0)
  • 2020-12-23 03:26

    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;
        }
    }
    
    0 讨论(0)
  • 2020-12-23 03:31

    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.

    0 讨论(0)
提交回复
热议问题