6

Assume that you have a C# method with a return statement inside a try block. Is it possible to modify the return value in the finally block?

The obvious approach, using return in the finally block, won't work:

String Foo()
{
    try
    {
        return "A";
    }
    finally
    {
        // Does not compile: "Control cannot leave the body of a finally clause"
        return "B";
    }
}

Interestingly, this can be done in VB: Return inside Finally is forbidden, but we can abuse the fact that (probably for reasons of backwards compatibility) VB still allows the return value to be modified by assigning it to the method name:

Function Foo() As String    ' Returns "B", really!
    Try
        Return "A"
    Finally
        Foo = "B"
    End Try
End Function

Notes:

  1. Note that I ask this question purely out of scientific curiosity; obviously, code like that is highly error-prone and confusing and should never be written.

  2. Note that I am not asking about try { var x = "A"; return x; } finally { x = "B"; }. I am aware that this doesn't change the return value and I understand why this happens. I'd like to know if there are ways to change the return value set inside the try block by means of a finally block.

Community
  • 1
  • 1
Heinzi
  • 167,459
  • 57
  • 363
  • 519

4 Answers4

22

Assume that you have a C# method with a return statement inside a try block. Is it possible to modify the return value in the finally block?

No.

You can however modify the return value outside the finally block:

static int M()
{
    try
    {
        try
        { 
            return 123;
        }
        finally
        {
            throw new Exception();
        }
    }
    catch
    {
        return 456;
    }
}

Just because there was originally a "return 123" does not mean that the method will return 123, if that's what your question is actually getting at. This method returns 456.

Eric Lippert
  • 647,829
  • 179
  • 1,238
  • 2,067
  • 1
    Very interesting. It appears the only exemption rule is when an exception is thrown inside the `finally` block. – Brad M Apr 16 '13 at 14:59
  • 5
    @BradM: You are correct. More generally: there are only three possible control flows within a `finally` block: (1) never leave, (2) leave normally, or (3) leave via thrown exception. Other control flows like `return`, `goto`, `break`, `continue`, `yield return`, `yield break` and `await` are either not legal in a finally block, or are only allowed if they jump to a location *within* the finally block. – Eric Lippert Apr 16 '13 at 15:09
0

The VB.NET version is abusing a vestigial construct from the VB6 era in which you return a value by assigning the value to the name of the function.

What would be really interesting to know is if there is a difference in the IL produced when using a standard return statement as opposed to myFunc = "B", as the try...catch...finally semantics would seem to dictate that it would be impossible to alter the value returned by a return statement.

w.brian
  • 16,296
  • 14
  • 69
  • 118
-1

You can do the following to approach the same effect:

private string myFunction()
{
    string result = String.Empty;
    try
    {
        //..
        result = "something";
    }
    finally
    {
        result = "something else";
    }
    return result;
}
Yami
  • 1,405
  • 1
  • 11
  • 16
  • 5
    Read the question again. The question begins "assume you have a return statement in a try block". Where is the return statement in your try block? – Eric Lippert Apr 16 '13 at 14:55
  • 1
    read my answer again.. ".. to approach the SAME EFFECT".. it is an alternative, not a solution, because it's not possible. no reason to vote down.. – Yami Apr 16 '13 at 16:26
-1

A close analogy with the cited VB approach would be assigning a revised value to the variable used by return (which has the benefit of conserving a single point of return of control):

string returnResult;

try
{
    returnResult = "A";
}
finally
{
    returnResult = "B";
}

return returnResult;
hardmath
  • 8,753
  • 2
  • 37
  • 65
PhonicUK
  • 13,486
  • 4
  • 43
  • 62
  • 1
    Read the question again. The question begins "assume you have a return statement in a try block". Where is the return statement in your try block? – Eric Lippert Apr 16 '13 at 14:54
  • There's nothing wrong on SO with telling the user "Don't do it like that, do it like this instead" - just giving them the answer to their question isn't always the right thing to do if what they're trying to do is wrong. – PhonicUK Apr 16 '13 at 14:56
  • 6
    The last paragraph of the question indicates that the original poster is aware that it is bad style. – Eric Lippert Apr 16 '13 at 15:01