Return vs. Finally (2)

Return vs. Finally (2)

The Return statement and finally have competition. Both can are the "last" thing to execute when a function exits, so which of them is really last? I blogged about this before regarding C#'s semantics setting data. Now I'll compare some interesting differences between C# and Python.

Who wins if you set them up in direct competition like this (non-exceptional path):

void f1()
{
try
{
return 10;
}
finally
{
return 5;
}
}

or this (the exceptional path):

void f2()
{
try
{
thrownewException();
}
finally
{
return 5;
}
}

There are multiple intelligent ways a language design could answer this.

C#'s answer: Illegal

In C#, this is just illegal. Returns are forbidden in finally clauses. This nicely just avoids the whole problem by refusing to let you write such potentially ambiguous and confusing code. (CS0157: "Control cannot leave the body of a finally clause"). And if a consensus emerges down the road that there really is a clear "right" answer, C# can always make it legal with the "right" semantics.

IL's answer: Illegal

The underlying CLR's IL instruction provides try/catch/finally and branching opcodes. The only branching opcode out of a finally is 'endfinally', which jumps to the end of the finally block. You can't return / branch out of a finally. (See VER_E_RET_FROM_HND=0x80131845 in CorError.h).

Since .NET languages compile to IL, it may be natural for a language to have the same semantics as the IL instructions it compiles to. It's not surprising that C# has the same restrictions as the underlying IL instruction set here. However, a .NET language can have more clever opcode usage to provide their own semantics.