I was playing about with Expression trees today for practically the first time and I wrote something like this.
object a = objectDictionary["somekey"]; Expression constExpr = Expression.Constant(a);
Eventually this expression went into a bunch more expressions and finally compiled into a delegate.
It wasn’t until afterwards that I went… wait… what? I had just passed a reference type to be a ‘constant’ in a delegate and it wasn’t even a string. Surely it will fail when I run it. But no, it works just fine.
I may not have written a lot of IL, but I did write a parser for the output of ildasm, so I like to pretend that I know a bit about what you can do in IL and I certainly couldn’t see any way you could embed a reference into some IL. And it certainly can’t be capturing a, since that rewrites the parent method and Expressions can’t do that…
So I turned to the trusty internet and found ILVisualizer, which I suspect I will be keeping on hand at all times from now on… and lo, the compiled delegate is closed, with the this parameter bound to an instance of CompilerServices.Closure. This type has an object array property called Constants, where my trusty reference has been stored and the generated delegate loads this and accesses the first element.
In part what I find interesting about this is that you can’t trivially write a lambda to do the same thing, since that will capture the variable, and subsequent changes will affect the lambda. Here we are guaranteed to get the value of the reference at the point in time the expression is constructed.
Nifty!