views:

249

answers:

5

Consider,

        static void Main(string[] args)
        {
            Console.WriteLine(fun());
        }

        static int fun()
        {
            int i = 0;
            try
            {
                i = 1;
                return i;
            }
            catch (Exception ex)
            {
                i = 2;
                return i;
            }
            finally
            {
                i = 3;
            }
        }

The sample code outputs "1". but the value of i is changed to 3 in finally block. Why wasn't the value of 'i' changed to 3?

Thank you,

+6  A: 

You have to remember that finally executes after everything else in the try and catch. Place the return statement after the try/catch/finally statement to have it return 3.

Kevin
We can't return from finally because it gives the error "Control cannot leave the body of a finally clause"
Mahesh
@Mahesh I forgot about that. thanks
Kevin
@Steve - Kevin modified his answer
Mahesh
+2  A: 

When you said "return i"... C# puts that return value in a temporary holding area (memory) and then runs your 'finally' code... if the finally block was able to modify that value, it would defeat the safety/finalism of the finally block.

It's like a using statement with a return inside... the "Dispose" is still going to happen, AFTER the return (so to speak).

Timothy Khouri
+1 Thats it. I was about to post simply "Because the return has already happened" but this answer is pretty much there.
AnthonyWJones
+11  A: 

Consider this code- I think the code explains what you are thinking, and how you can make what you think should happen actually happen:

static void Main(string[] args)
{
    int counter = 0;
    Console.WriteLine(fun(ref counter)); // Prints 1
    Console.WriteLine(counter); // Prints 3
}        

static int fun(ref int counter)
{
  try
  {
      counter = 1;
      return counter;
  }
  finally
  {
      counter = 3;
  }
}

With this code you return 1 from the method, but you also set the counter variable to 3, which you can access from outside the method.

RichardOD
+1  A: 

Finally is always executed

Your code always executes finally no matter if an exception was thrown or not. So your code should actually be:

try
{
    i = 1;
}
catch
{
    i = 2;
}
finally
{
    i = 3;
}
return i;

But in this trivial case finally block won't make much sense. Because we will always return 3 no matter what happened before that.

Finally is used to release resources

finally block should normally be used when you have to release some system resources allocated within try block (ie. openning a DB connection an reading data in try block and closing it in finally). So they will always get released no matter if there was an exception or not. In this case it doesn't make much sense to use finally block.

Robert Koritnik
I would ask person that voted my answer -1 to clarify their decision.
Robert Koritnik
+2  A: 

I imagine if you use a reference type instead of a value type you'd get different behavior.

+1. Yes, you are right.
Mahesh
True, but the real question is: at what point in a try/catch/finally does the return value get pushed on the stack for non-reference parameters?
Joe
+1. I think that is a very good point. I wish I had put that in my answer too!
RichardOD