从多个按钮订阅相同方法(?)来看匿名方法

多个按钮绑定一个回调函数时……

等等,回调?

回调函数,或简称回调( Callback 即 call then back 被主函数调用运算后会返回主函数 ),是指通过函数参数传递到其它代码的,某一块可执行代码的引用。这一设计允许了底层代码调用在高层定义的子程序。

事件处理函数。

有这样一个需要,在脚本中对多个按键绑定处理方法,但是这些按钮的功能是很类似的,区别只在于一一对应的关系不同,分别操控不同的对象做相同的动作。因此在处理函数中只需要区分按下了哪一个按钮,并找到相对应的对象就可以了。但在绑定处理函数时,往往是不能直接传递参数的,因此想到了,可以通过匿名函数,在作用域内,将局部变量用在匿名函数中去。看一下代码:

使用 delegate 来完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public List<Button> btnList;
public override void Start()
{
base.Start();
}

public bool foo()
{
for (int i = 0; i < 4; i++)
{
int temp = i;
btnList[temp].onClick.AddListener(
delegate
{
BtnClicked(temp);
}
);

}
}

public void BtnClicked(int index)
{
...
}

这里的 temp 是不能够省略的,如果直接使用 i,会在后面的事件处理函数中越界,我猜测是与 for 会清理有关系吧?(等等等等我问问问问试试试试一下)

正常有 c# 经验的人应该都认得出这是个匿名函数吧,我也隐约觉得这是个匿名函数,可能是特殊的用法?其实在我的意识里,早就潜移默化的错误的把匿名函数与 lambda 表达式等看了价在一起了,这是错误的错误的错误的。

lambda 表达式只是通常用匿名方法来解释比较通俗,而匿名方法实际上并不是传统意义上的方法或属于某个类的方法,它纯粹是为了用作委托的目的才创建的:

1
2
3
delegate (parameters) {
// Anonymous method code
}

这才是匿名方法的最常见的用法呀!@

而本例中,利用了匿名函数最显著的一个优势,对于包含匿名方法的代码块来说,匿名方法是局部的,因此匿名方法是可以访问到这个代码块中的局部变量的,而这个被匿名函数使用的局部变量也就成为了外部变量(Outer Variable)(在超出作用域时是不会删除的,匿名方法销毁时,相关外部变量才会删除,前后有延迟,比我们期望的会晚一些)。

匿名方法是提供的匿名方法,可以用 lambda 表达式代替(待展开)。

关于参数,当 lambda 表达式没有参数时需要用一个括号代替(保留括号),而 delegate 的方法可以完全将其省略。