Delegate Magic
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 ourint[]in it. L_0000toL_000enews up an instance of<>c__DisplayClass1and assigns theiafield therein to a newint[]of size 1.L_0013toL_001bassigns the value 2 to element 0 ofiawithin the instance.L_001ctoL_0028news up aFunc<int>, passing to the constructor the reference to<>c__DisplayClass1and the address of a method on<>c__DisplayClass1called<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.

All kinds of interesting stuff on the perils of auto-closures here: http://bartdesmet.net/blogs/bart/archive/2008/10/26/about-cruel-lambdas-closures-typedreferences-cs0610-and-other-things-you-shouldn-t-do.aspx.
skepticabin
October 27, 2008 at 6:45 AM