注意点:
1、创建委托实例不会先执行
2、对于一个捕获变量,只要还有任何委托实例在引用它,他就会一直存在。
3、每个委托各自维护各自的捕获变量
4、判断这个一个变量是否是多个委托共用的,判断在创建委托时候这个变量是否重新创建了
1、捕获周期变长了,下面的例子在调用CreateDelegateInstance()方法后,猜测存在函数对应的栈上的局部变量counter就已经销毁了,事实是编译器创建了个额外的类来容纳变量,存放到堆上了。而且委托对该实例也有引用,所以除非委托准备好垃圾回收,否则这个实例是不会被回收的。
static Action TestDeleParameter()
{
int counter = 100;
Action retDel = delegate
{
System.Windows.MessageBox.Show(counter.ToString());
counter +=100;
};
retDel();
return retDel;
}
//调用
Action dele = TestDeleParameter();
dele();
dele();
结果是100、200、300
2、注册了5个委托,每个委托实例都各自引用了counter捕获变量,而且每个委托的counter的捕获变量都是各自委托自己维护的,所以执行第一个委托(lisDele[0]),第一个委托的counter执行相对应的变化,而不会影响剩下四个捕获变量counter的变化。
List<Action> lisDele = new List<Action>();
for(int i=0; i<5; i++)
{
int counter = i * 10;
lisDele.Add(delegate
{
System.Windows.MessageBox.Show(counter.ToString());
counter++;
});
}
lisDele[0](); //0
lisDele[1](); //10
lisDele[2](); //20
lisDele[3](); //30
lisDele[4](); //40
//下面循环输出:1、11、21、31、41,因为上面五行代码已经执行了五个委托一次,所以各自的
//counter都进行了++,所以会有如此的结果
foreach (var methodInvoker in lisDele)
{
methodInvoker();
}
//此时第一个委托的counter值为2,所以有以下如此输出
lisDele[0](); //2
lisDele[0](); //3
lisDele[0](); //4
lisDele[1](); 12
3、使用i作为捕捉变量,这个i就是这五个委托共用的,因为这个i是在创建这五个委托时候没有进行过重新创建,始终是同一个变量
List<Action> lisDele = new List<Action>();
for (int i = 0; i < 5; i++)
{
//int counter = i * 10;
lisDele.Add(delegate
{
System.Windows.MessageBox.Show(i.ToString());
i++;
});
}
lisDele[0](); //5
lisDele[1](); //6
lisDele[2](); //7
lisDele[3](); //8
lisDele[4](); //9