Getting closure variable’s data from lambda expression in C#

2 minute read | April 23, 2017

Hi everyone! Today I want to talk about closures and extracting their values from lamda expression.

The problem

One of my project has a lot of Action and Func delegates as parameters for methods. It has them everyevere and I got a task to write some unit-tests for some of these methods. Let’s imagine that there is a method that take Action like a parameter.

        public void Execute(Action action)
        {
            //... Some code
            action();
            //... Some code
        }

The delegate can be initialised with lambda expression.

        var thisIsClosure = "ThisIsClosure";
        Action actionWithClosure = () =>
        {
            Сonsole.WriteLine(thisIsClosure);
        };

So, we call them in a way like in a snippet below.

	Execute(actionWithClosure);

What I did

Because I was writing unit-tests I had to get some values from Action for Asserts. But It tended to be a real problem, because I couldn’t use Expression, because code smells when you change it for testing reasons.

Please Note: If you change your code, due to some unit-tests reasons, it’s the awful practice. Please, don’t do this.

So, I decided to write a simple parser with using of Reflection.

    public static class LambdaVariableExtractor
    {
        public static TValue ExtractValue<TValue>(
		this Delegate lambda, 
		string variableName)
            where TValue : class
        {
            if (lambda == null)
                throw new NullReferenceException("Empty lambda");

            var field = lambda.Method.DeclaringType?.GetFields
                (
                    BindingFlags.NonPublic |
                    BindingFlags.Instance |
                    BindingFlags.Public |
                    BindingFlags.Static
                )
                .Single(x => x.Name == name);

            if (field == null)
                throw new NullReferenceException("There isn't a variable with this name");


            return field.GetValue(lambda.Target) as TValue;
        }
    }

In this code, first of all we check lambda expression for exisiting and then do some magic. What is a DeclaringType in this context? For uderstanding this, we should take a short look on some parts of C# specification.

As we all know, lambda expressions are just sugar.

7.15 Anonymous function expressions An anonymous function is an expression that represents an “in-line” method definition. An anonymous function does not have a value or type in and of itself, but is convertible to a compatible delegate or expression tree type. The evaluation of an anonymous function conversion depends on the target type of the conversion: If it is a delegate type, the conversion evaluates to a delegate value referencing the method which the anonymous function defines. specification

In this context lambda is some kind of anonymous function. Let’s take a look, how compilator doing some job for us.

Generated class

There is a class named the strange name <>c__DisplayClass0_0 in the picture. And this is a class which was generated by compilator. Usually this class contains only your lambda as a method. But sometimes, when you have closures it starts to contain some variable. In example, you can see that there is thisIsClosure variable there.

So, DeclaringType returns Type for this generated class. After that it’s easy to fetch fields of this class. And the last thing, If you want to get values from these fields you should pass Target as the parameter to the GetValue function. Target keeps reference to the object of the generated class and we need to pass it for right working of Reflection.

You can find this example’s code on github.

Conclusion

That’s all. I’ll be happy, If this article helps you.

Leave a Comment