The Limber Lambda

Delegate Magic

Posted in Fun by Eric Smith on October 13, 2008

So, you’ve used delegates with gay abandon and everything just seems to work.  In particular, this sort of thing works without a hitch:

	class Proggy
	{
		public static void Main(string[] args)
		{
			var p = new Proggy();
			Console.WriteLine(p.StuffThatNeedsDoing()());
			Console.ReadLine();
		}

		public Func<int> StuffThatNeedsDoing()
		{
			var ia = new int[1];
			ia[0] = 2;
			return (() => ia[0] * ia[0]);
		}
	}

I’m referring, of course, to the bit that returns a delegate that references a method variable. I’ve always been curious as to how that works, so I dug into the IL to reveal the magic.

The interesting bit is the implementation of StuffThatNeedsDoing():

Let’s take a closer look as to what is happening here:

  • Behind the scenes, the compiler generates a nested class called <>c__DisplayClass1
    and encapsulates our int[] in it.
  • L_0000 to L_000e news up an instance of <>c__DisplayClass1 and assigns the ia field therein to a new int[] of size 1.
  • L_0013 to L_001b assigns the value 2 to element 0 of ia within the instance.
  • L_001c to L_0028 news up a Func<int>, passing to the constructor the reference to <>c__DisplayClass1 and the address of a method on <>c__DisplayClass1 called <StuffThatNeedsDoing>b__0 (which turns out to be our delegate implementation).
  • The new Func<int> is then effectively returned.

In short – it looks (unsurprisingly) like the local ia is no longer a local, and naively referencing it from within the delegate has caused it to be treated like a heap variable.  Of course our “local” ia now has a lifetime consistent with the lifetime of the delegate returned by StuffThatNeedsDoing—not a problem if we don’t mind, but what if we had referenced a “local” IDataReader from within our delegate?  The IDataReader, and associated unmanaged resources, would lurk around possibly for a very long time … something to be aware of.

So, as it turns out, the thing that binds a function to it’s “environment” (in this case, the local that we referenced) is known as a closure.

Tagged with: , ,

Polyglot

Posted in Fun by Eric Smith on September 12, 2008

Well, polyglot programs are curious beasts, but what really takes the cake is renaming a text file to .com and seeing it run!

Follow

Get every new post delivered to your Inbox.