Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is my finally block not working in C#?

Tags:

c#

finally

I've been helping a colleague debug some strange behavior in their code. The following sample illustrates this:

static void Main(string[] args)
{
    string answer = Sample();
    Console.WriteLine(answer);
}

public static string Sample()
{
    string returnValue = "abc";

    try 
    {
         return returnValue;
    }

    catch (Exception)
    {
         throw;
    }

    finally
    {
         returnValue = "def";
    }
}

What does this sample return?

You'd think that because of the finally block, it returns "def" but in fact, it returns "abc"? I've stepped through the code and confirmed that the finally block is in fact invoked.

The real answer is that you shouldn't write code like this in the first place but I'm still puzzled as to the behaviour.

Edit: To clarify the flow based on some of the answers.

When you step through the code, the finally is executed before the return.

Duplicate of: What really happens in a try { return x; } finally { x = null; } statement?

like image 442
rbrayb Avatar asked Mar 24 '09 00:03

rbrayb


2 Answers

Your "finally" block is assigning a value to returnValue and not actually returning a value. The "return" has already occurred before the finally block changes the value and therefore "abc" is returned.

Whilst the code is confusing as what you've done doesn't make sense, what it's doing is correct.

like image 177
Robin Day Avatar answered Sep 22 '22 03:09

Robin Day


Yes, the finally block runs after the function returns, but this doesn't matter. Remember that the return value is passed by value, so a new temporary variable is created for it at return time, thus the finally block does nothing to affect the actual return value. If you want to support the desired behavior you could use an out parameter, like so:

static void Main(string[] args)
{
    string answer;
    Sample(out answer);
    Console.WriteLine(answer);
}

public static void Sample(out string answer)
{

    try
    {
        answer = "abc";
        return;
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        answer = "def";
    }
}

Or, you could simply move the return statement outside of the try block, like so:

static void Main(string[] args)
{
    string answer = Sample();
    Console.WriteLine(answer);
}

public static string Sample()
{
    string returnValue;
    try
    {
        returnValue = "abc";
    }

    catch (Exception)
    {
        throw;
    }

    finally
    {
        returnValue = "def";
    }

    return returnValue;
}

However, given that the finally block will always override the return value, this is a questionable design.

like image 26
Wedge Avatar answered Sep 20 '22 03:09

Wedge