Extracting closure variable’s data from lambda expression in C#
Hi everyone! Today I want to talk about closures and extracting their values from lamda expression.
This article is the second version of the article in my blog. So, let’s get it started.
One of my project has a lot of
Func delegates as parameters for methods. It has them everywhere 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
Actionlike a parameter.
The delegate can be initialized with lambda expression.
So, we call them in a way like in a snippet below.
Because I was writing unit-tests I had to get some values from
Asserts. But It tended to be a real problem, because I couldn’t use
Expression, because of some historical reasons.
So, I decided to write a simple parser with using of
I have created a library which contains a simple helper. You can find it on github. Also, you can install it by
In the next sections of the article, I’ll tell and show you, how this helper works.
What I did
In this code, first of all we check lambda expression for existing and then do some magic. What is a
DeclaringType in this context? For understanding this, we should take a short look on some parts of C# specification. As we all know, lambda expressions are just syntactic 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.
In this context lambda is some kind of anonymous function. Let’s take a look on a few examples.
Here is the simple unit-test which contains lambda with closure.
The code below shows how compilator doing some job for us.
There is a class named the strange name
<>c__DisplayClass0_0. 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
closure variable there.
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
Target keeps reference to the object of the generated class and we need to pass it for right working of
Reflection. In the example
Targetkeeps reference to
That’s all. I’ll be happy, if this article helps you.