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?
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With