I understand that variable capturing is done by the compiler and not by the classes in the .NET framework itself. However, when the DLR was introduced, some of this work must surely have needed to have been done within the framework so as to defer it to runtime.
For e.g., in the piece of code given below:
dynamic d = ...
Func<int, bool> func = n => n > d;
The type resolution of the variable d
and its verification that it is an integer must have to be done at run-time. And since d
is a variable in the containing method of the lambda, it will be captured into a closure. This part will surely be done at run time.
Hence, I infer there must be some part of the DLR assemblies (System.Core.dll mostly) that does this part.
I've been searching and I could find some classes that look suspiciously reprehensible for this sort of a task. Specifically, ExpressionQuoter (despite the looks of it, this class does not quote lambda expressions like the Expression.Quote
method does), HoistedLocals, and the VariableBinder.
I thought I would invite someone who knows better to answer this.
Which class or part of the .NET framework turns locals that are in containing methods of lambdas (or anonymous methods) into those separate classes that have static variables representing them?
And since d is a variable in the containing method of the lambda, it will be captured into a closure.
d
does not need to be captured because the lambda is not using it. If the C# compiler chooses to capture it (which is not forbidden under the as-if rule) it will not be accessed in any way.
I believe func(d)
is executed like any method call with a dynamic argument would be.
Let's look at:
dynamic d = ...; //maybe "1"
Func<bool> func = (() => d == "1234");
I think this is more in the spirit of what you want to know (Update: Indeed you just edited the question to have this pattern). The lambda depends on d
now which was not the case before.
Here, d
is captured in the generated closure class as a field of type object
. dynamic
is always compiled as object
(potentially with a custom attribute on it). The lambda code body then proceeds to use standard dynamic operations.
Because all variable references in C# are statically bound to a particular variable there is never a need to capture a dynamic number of fields or something like that. The fields to capture are statically known.