0%

CSharp闭包

闭包是指有权访问另一个函数作用域中的变量的函数

局部方法调用外部参数时会将传入的参数封装到一个类中

静态局部方法或静态匿名表达式不能访问外部参数, 因此不会形成闭包

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
int count = 0;
//此处将count封装到一个类中传入
var demo = new Demo(()=>count++);
//count = 0
demo.Do();
//count = 1
class Demo()
{
private readonly Action _callBack;
public Demo(Action action)
{
_callBack = action;
}
public void Do()
{
_callBack.Invoke();
}
}
1
2
3
4
5
6
7
8
9
10
var cnt = CreateCounter();
cnt.Invoke();//counter = 1
cnt.Invoke();//counter = 2
cnt.Invoke();//counter = 3
cnt.Invoke();//counter = 4
Action CreateCounter()
{
int counter = 0;
return ()=>Console.Write(++counter);
}

问题分析

1
2
3
4
5
6
7
8
9
10
11
12
13
var actions = CreateActions();
actions[0].Invoke(10);
actions[1].Invoke(10);
actions[2].Invoke(10);
Action<int>[] CreateActions(int count = 3)
{
var actions = new Action<int>[count];
for(int i = 0; i < count; i++)
{
action[i] = x => Console.WriteLine(x * i);//此处传入匿名函数时会在for循环外将i封装到一个类中, 导致最终的i为3, 具体可看编译后的IL
}
}
//输出均为30
1
2
3
4
5
6
7
8
9
10
11
12
13
14
var actions = CreateActions();
actions[0].Invoke(10);
actions[1].Invoke(10);
actions[2].Invoke(10);
Action<int>[] CreateActions(int count = 3)
{
var actions = new Action<int>[count];
for(int i = 0; i < count; i++)
{
int j = i;
action[i] = x => Console.WriteLine(x * j);//此处传入匿名函数时会在for循环内将j封装到一个类中
}
}
//输出均为0, 10, 20