24

As MSDN mentions:

The code in a Finally block runs after a Return statement in a Try or Catch block is encountered, but before that Return statement executes. In this situation, a Return statement in the Finally block executes before the initial Return statement. This gives a different return value. To prevent this potentially confusing situation, avoid using Return statements in Finally blocks.

As I didn't understand a lot from this note, I'll take an example (VB.NET, I think in C# is the situation is similar):

Try
    HugeOp()
    Return "OK"
Catch
    Return "NOK"
Finally
    Return "Finally"
End Try

Now, why should be this illegal in both C# and VB.NET?

serhio
  • 28,010
  • 62
  • 221
  • 374
  • what happens when you run it? – Mitch Wheat Apr 26 '11 at 09:03
  • 3
    As I always recommend, just make a small test program to emulate the case and see for yourself. – Dmitry Apr 26 '11 at 09:04
  • 3
    it is ***illegal*** in C# (edit: and, it seems, VB) – Marc Gravell Apr 26 '11 at 09:04
  • @serhio: so there's your answer – Mitch Wheat Apr 26 '11 at 09:04
  • @Marc Gravell: this is illegal in VB.NET, as well. – serhio Apr 26 '11 at 09:05
  • 1
    @Mitch Wheat: The question was ***WHY*** this – serhio Apr 26 '11 at 09:05
  • I'm not sure I'm clear on the question being asked. Did you run the code? What did it return? – izb Apr 26 '11 at 09:06
  • 2
    @serhio ah, then MSDN is confusing ; a better remark in MSDN would be "avoid using Return statements in Finally blocks, else your code won't compile"; I have annotated MSDN to this effect. – Marc Gravell Apr 26 '11 at 09:06
  • possible duplicate of [What really happens in a try { return x; } finally { x = null; } statement?](http://stackoverflow.com/questions/421797/what-really-happens-in-a-try-return-x-finally-x-null-statement) – Matt Ellen Apr 26 '11 at 09:07
  • @Marc Gravell♦: Why do in general mention phrases like "*avoid* using Return out of the method blocks, else your code won't compile"? Instead a phrase like `The .NET compilers (C#, VB) does not allow the using of "Return" in the finally locks, because of bla bla...` would be more appropriate... – serhio Apr 26 '11 at 11:22
  • @Matt Ellen: 2 different questions – serhio Apr 26 '11 at 11:24
  • @serhio - the note in MSDN *does* give reasoning. My point is that it isn't an "avoid" thing (which sounds like a recommendation); it **will not work** – Marc Gravell Apr 26 '11 at 11:24
  • @Marc Gravell♦: Ya ya, that was my point. But your "better remark" still keeps the "avoid" word... ) – serhio Apr 27 '11 at 11:43
  • 5
    An interesting side note: this is *not* illegal in JavaScript. `function m() { try { return 1; } finally { return 2; } }` a call to `m()` will return 2. Implementing that was a real pain for the development team. It's also legal in Java. – Eric Lippert Apr 16 '13 at 15:49

3 Answers3

34

It's illegal because when you reach the Finally block, the value to return is already defined ("OK" if everything went well, "NOK" if an exception was caught). If you were able to return a different value from the Finally block, this value would always be returned, whatever the outcome of the instructions above. It just wouldn't make sense...

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • thank you. So "Finally" should be the return value. Made illegal to "de-confuse" the code. – serhio Apr 26 '11 at 09:17
  • 1
    No, the return value is set *before* the return statement is executed. Inbetween those two things, the finally block is executed. It therefore makes no sense to have a return statement in a finally block. It doesn't make sense to say that finally "should" be the return value because it doesn't makes sense for finally to *have* a return value. – izb Apr 26 '11 at 09:22
  • @izb: In other words, in my success case, the compiler takes "OK" as return value, executes the Finally block, then takes the "OK" and effectively returns it? – serhio Apr 26 '11 at 09:26
  • 12
    The specification could define the behavior of `return` in a finally statement however it likes. It could return the old return value, the new return value or be illegal. Any if these behaviors is possible, and they chose to make it illegal. And I agree with that decision. – CodesInChaos Apr 26 '11 at 09:58
  • This has nothing to do with the return value being set already. You could delete the first two returns and you'd get the same error,. – usr Jun 26 '16 at 13:09
  • @usr, if you have a better explanation, feel free to post an answer ;) – Thomas Levesque Jun 26 '16 at 13:43
  • It is not required to post an answer in order to point out a flaw in an existing one. – usr Jun 26 '16 at 13:45
  • @usr, indeed. To give a more useful answer to your comment, what you said is true, but consider this: it makes sense to forbid `return` in `finally` if you already returned something in the `try` or `catch`; it *could* be allowed when you *didn't return anything* in the `try` or `catch`, but it would be inconsistent. I think the language designers just wanted to avoid the inconsistency. Of course, it's just my guess; to know the true reason, you'd have to ask the language designers themselves ;) – Thomas Levesque Jun 26 '16 at 13:56
2

I was curious about this, I'm running VS2010 and does not allow a Return in the finally block. here is the code I compiled

Public Class Class1
   Public Shared Function test() As String
      Try
         Return "OK"
      Catch ex As Exception
         Return "Catch"
      Finally
         test = "Finally"
      End Try
   End Function
End Class

I compiled the DLL to view the MSIL it looked rather interesting the above code basically gets refactored to this:

Public Class Class2
   Public Shared Function test() As String
      Try
         Try
            test = "OK"
         Catch ex As Exception
            test = "Catch"
         End Try
      Finally
         test = "Finally"
      End Try

      Return test
   End Function
End Class

and testing this out, the MSIL for the above two classes is exactly the same.

Apeiron
  • 694
  • 7
  • 13
  • so, finally, you found a way to return in finally block in Visual Basic, using the function's name, even if confusing, there is a way to do it... – serhio Apr 21 '13 at 07:27
1

I guess the answer is in the question. It's illegal because it's confusing. It's not intuitive which value will be returned. If it's illegal, you are forced to write code where the flow is much clearer.

izb
  • 50,101
  • 39
  • 117
  • 168
  • "confusing", "intuitive", but really what should be the return here after the compiler rules? Is it always "Finally"? – serhio Apr 26 '11 at 09:12
  • 1
    Looks like the compiler rules state it's illegal and shouldn't compile. So the question what it does return makes no sense. – CodesInChaos Apr 26 '11 at 09:16
  • @CodeInChaos: read the note I posted. "This gives a different return value." – serhio Apr 26 '11 at 09:19
  • You're note is obviously inaccurate and doesn't describe the behavior of either C# or VB.net. That's why @MarcGravell suggested that the documentation should be updated to be consistent with the actual behavior of the compiler. – CodesInChaos Apr 26 '11 at 09:31
  • @CodeInChaos: I am not sure if in Visual Studio this kind of "Error" could not be "downgraded" to a Warning... – serhio Apr 26 '11 at 09:45
  • 2
    Making it a warning would violate the spec. "8.9.4 The return statement" - "It is a compile-time error for a return statement to appear in a finally block" (From the C# specification) – CodesInChaos Apr 26 '11 at 09:56