61

When I place a return inside the block of a finally statement, the compiler tells me:

Control cannot leave the body of a finally clause

Example:

try
{
}
catch
{
}
finally
{
    return;
}

Why is this?

user247702
  • 23,641
  • 15
  • 110
  • 157
Mike Baxter
  • 6,868
  • 17
  • 67
  • 115

3 Answers3

90

Consider what would happen if you were to return 1 inside the try block and return 0 inside the finally block... Your function would be trying to return two values! The combined options of try and catch are exhaustive in terms of control flow.

Alex
  • 7,639
  • 3
  • 45
  • 58
26

It's by design and it's described in C# specification:

It is a compile-time error for a break, continue, or goto statement to transfer control out of a finally block. When a break, continue, or goto statement occurs in a finally block, the target of the statement must be within the same finally block, or otherwise a compile-time error occurs.

It is a compile-time error for a return statement to occur in a finally block.

Also, from C# 6.0 spec draft on MSDN:

It is a compile-time error for a return statement to occur in a finally block.

MarcinJuraszek
  • 124,003
  • 15
  • 196
  • 263
  • Your link is rotten, but I couldn't find the new version. – ANeves Jan 04 '19 at 14:54
  • @ANeves I couldn't either. The spec ships with every Visual Studio, so the quote is still valid, just not the link. I added a new one to C# 6.0 spec draft, which has the same statement. – MarcinJuraszek Jan 04 '19 at 16:03
-10

Current answers explain why this happens well, but I also think it's important to note how easy it is to circumvent this constraint in the case where no return value is involved, and the finally clause is the last thing in the method (which happens often):

try {}
catch {}
finally
{
    FinallyMethod();
}

Then in FinallyMethod you can use return statements as much as you'd like

void FinallyMethod()
{
   //...
   if (x == y)
       return;
   else
       a = b;
   //etc.
}
Ohad Schneider
  • 36,600
  • 15
  • 168
  • 198
  • 3
    Returning inside `FinallyMethod` won't do anything for the method containing the try/catch/finally. – user247702 Jan 05 '17 at 11:02
  • Just because you `return` from `FinallyMethod` won't make you return from the calling site. – Hatted Rooster Jan 05 '17 at 11:03
  • 2
    Of course, but it can be useful for control flow, e.g. `if (!x) return; //do a lot of stuff`. So you can use `return` in `FinallyMethod` for that purpose instead of doing everything under nested `if` clauses. – Ohad Schneider Jan 05 '17 at 15:53
  • OK, I understand now what you mean now. But it's not really relevant to the example in the question, because you wouldn't be using `return` in the `finally` block to begin with, when using your example. – user247702 Jan 06 '17 at 10:01
  • 2
    @Stijn I agree it's not fully relevant, just a tip in case the last thing in your method is the `finally` clause (which very often is the case) and then using the method I suggested is equivalent to using `return`. I've clarified that in my answer. – Ohad Schneider Jan 06 '17 at 13:37