Thursday, November 27, 2008 #

C# quiz - try-finally

So what is the output for following program?

public class SimpleTest

{

      public static void Main(string[] args) {

            Console.WriteLine(GetString());

            Console.ReadLine();

      }

     

      private static string GetString() {

            string str = "original string";

            try {

                  return str;

            } finally {

                  str = "changed in finally";

            }

      }

}

It looks very simple, but most of my developer friends and I all had the wrong answer. In the college, we were all told that finally block is guaranteed to be executed before a method returns, right? So it should display “changed in finally”, shouldn’t it? Unfortunately, this is a wrong answer. The program will actually print “original string”!

So, why? The answer is pretty simple. Though “return str;” is just one statement in C#, it is made of a few IL instructions. So if we have a look the complied IL code, the program first loads the “original string” and stores it in location0, then in the try block, it loads the value from lcoation0 and then store it into location1. In the finally block, it loads string “changed in finally” and store it to location0. And at the end, it loads the value from location1 onto stack for return value and exits the method.

So we can simply put, the string “original string” is prepared for return before the finally block gets executed, that is why the “original string” was returned from the method.

.method private hidebysig static string  GetString() cil managed

{

  // Code size       24 (0x18)

  .maxstack  1

  .locals init (string V_0,

           string V_1)

  IL_0000:  nop

  IL_0001:  ldstr      "original string"

  IL_0006:  stloc.0

  .try

  {

    IL_0007:  nop

    IL_0008:  ldloc.0

    IL_0009:  stloc.1

    IL_000a:  leave.s    IL_0015

  }  // end .try

  finally

  {

    IL_000c:  nop

    IL_000d:  ldstr      "changed in finally"

    IL_0012:  stloc.0

    IL_0013:  nop

    IL_0014:  endfinally

  }  // end handler

  IL_0015:  nop

  IL_0016:  ldloc.1

  IL_0017:  ret

} // end of method SimpleTest::GetString

Posted On Thursday, November 27, 2008 9:01 PM | Comments (13)

Copyright © Changhong Fu

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski