finally and Return Values !!!

HKT HKT
Views

Let us read some code:-

int SomeMethod()
{
    int num = 1;

    try
    {
        num = 5;
        return num;
    }
    finally
    {
        num += 5;
    }
}

What is the return value of SomeMethod? Some anonymous guy asked that question in the code project forum, and it has been answered. I am writing about it here because it is interesting and subtle. One should not be surprised when people misinterpret finally. So let us take a guess, 10 (i = 5, then incremented by 5 in the finally block).It is not the right answer; rather SomeMethod returns 5. Agreed that finally is called in all cases of returning from SomeMethod but the return value is calculated when it is time to return from SomeMethod, normally or abnormally. The subtlety lies not in the way finally is executed but in the return value is calculated. So the return value (5) is decided when a return is encountered in the try block. The finally is just called for cleanup; and the num modified there is local to SomeMethod. So make the return value 10, it is no use being hasty making SomeMethod return from the finally block. Because returning from finally is not allowed. (We will talk about it later why returning from catch block is a bad practice and why can’t we return from finally block). Had such modifications been done on a reference type, they would have been visible outside of SomeMethod, although the return value may be different.

For instance,

class Num
{
    public int _num = 0;
};

int SomeMethod()
{
    Num num = new Num();

    try
    {
        num._num = 5;
        return num._num;
    }
    finally
    {
        num._num += 5;
    }
}

So in the above case, the return value is still 5, but the Num._num would have been incremented to 10 when SomeMethod returns. So reflecting shows that our code is transformed as follows by the compiler, where the CS$1$0000 is our return value.

private static int SomeMethod(Num num)
{
    int CS$1$0000;

    try
    {
        num._num = 5;
        CS$1$0000 = num._num;
    }
    finally
    {
        num._num += 5;
    }

    return CS$1$0000;
}

Given that we have clarified ourselves about finally, we should be writing the code as transformed by the compiler because returning from try and catch blocks is not a good practice.

C# codeproject finally