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

This article is part of the GWB Archives. Original Author: Changhong Fu

New on Geeks with Blogs

  • We Won The One Award I Actually Care About

    Full Scale made the Inc. 5000 for the fifth year straight, the 12th listing across my three companies. Here is why the one award you cannot buy is worth stopping for.

  • Your Customers Build the Features Now

    I let a tool I liked sit dead for a year rather than build the features I wanted. An MCP server meant I never had to, and your customers can do the same to your product.

  • Get the Size of a Directory in Linux the Easy Way

    du -sh for the quick answer, ncdu for the cleanup, df for the disk itself: every command for checking directory size in Linux, plus why du and df never agree.

  • Vim Search and Replace: The Ultimate Guide

    One :%s command replaces every match in a file before a find dialog would even open. The Vim substitute patterns worth the muscle memory: flags, ranges, capture groups, and multi-file edits.