Here is an example of using the action delegate:
static void Main(string[] args)
{
int i = 0;
Action a = () => i++;
a();
a();
Console.WriteLine(i);
}
The result is expected 2. But the curious thing is: how is the variable I on the stack passed to the action delegate?
Check the reverse compilation. First, check the Il code corresponding to the main method:
Let's look at the Il code of c_displayclass1:
We can see that:
→ An Instance named c_displayclass1 is created on the hosting stack.
→ Assign the value of the stack variable I to the instance field I of c_displayclass1.
→ Compiler () => I ++; A <main> B _0 method name is delegated anonymously in the lambda expression and becomes an instance method of c_displayclass1.
→ Assign the instance method <main> B _0 of c_displayclass1 to the delegate variable of action.
→ The last call to the delegate is twice, both of which are for the instance field I of c_displayclass1
In other words, an object instance is created on the hosting stack to form a closure ". The variables on the stack become the instance fields of the closure, and the anonymous delegate represented by the lambda expression becomes the instance method of the closure.
Above, an action is created to form a "closure". Then, two actions are created to form two "closures". Check whether the instance fields of "closure" affect each other?
static void Main(string[] args)
{
Action a = GetAction();
Action b = GetAction();
Console. Write ("the value of the first call of a and I = ");
a();
Console.WriteLine();
Console. Write ("the second call of a, I value = ");
a();
Console.WriteLine();
Console. Write ("the value of B, I is called for the first time = ");
b();
Console.WriteLine();
}
static Action GetAction()
{
Action result = null;
int i = 0;
result = () => Console.Write(i++);
return result;
}
In the preceding example, although the same getaction method is assigned to the action delegate, the getaction method is in different "closures". When you call the delegate to execute the getaction method, the instance field I in the closure is automatically increased by 1 and printed.
Conclusion: each action has its own "closure", and "closure" does not affect each other.
"Delegation, lambda expressions, and event series" include:
Delegate, Lambda expression, event series 01, Delegate, basic delegate usage, delegate method and Target attribute delegate, Lambda expression, event series 02, when should I use delegate, Lambda expression, event series 03, from delegate to Lamda expression?
Delegation, lambda expressions, event series 04, how the delegation chain is formed, multicast delegation, calling the delegation chain method, delegation chain Exception Handling delegation, lambda expressions, event series 05, action delegate and Closure
Delegate, Lambda expression, event series 05, Action delegate and Closure