Lambda闭包应用_无参Lambda中调用有参函数
如果不使用Lambda表达式的闭包操作,在一个无参函数中调用有参函数,那么我们就需要在无参函数中为有参函数创建起需要的函数。但在一些情况下这种创建参数的代码往往是重复的。比如:
我们想要在遍历UGUI控件的同时找到所有的Button并为他们添加点击事件这项需求,和我们想要在遍历UGUI控件的同时找到所有的Toggle并为他们添加值改变事件这项需求。
同时为了区分不同的Button或Toggle我们需要一个参数来作为标识,比如不同Button的名字是不同的,我们就可以使用string参数来作为标识。
如果是不使用Lambda表达式闭包,我们可以将遍历控件查找指定类型这一部分代码单独提成一个方法来供两种情况调用。但是这样做是消耗性能的。每多一种情况就意味着多进行一次for循环。那我们可不可以只使用一次for循环遍历所有情况呢,当然可以这时候就需要使用到Lambda闭包。
为什么这个时候会使用到Lambda闭包?
因为将for循环提前会创造这样一种代码结构:
private void FindChildrenWidgets<T>() where T : UIBehaviour
{
//在子类中寻找所有的UI控件
T[] widgets = GetComponentsInChildren<T>();
for (int i = 0; i < widgets.Length; i++)
{
//获得所有控件的标识,这里以名字作为标识
string objName = widgets[i].gameObject.name;
if (widgets[i] is Button)
{
}
else if (widgets[i] is Toggle)
{
}
}
}
默认点击事件是一个无参无返回值签名的事件,这意味着响应函数也需要是无参无返回值的,但如果是无参无返回值我们就不能具体区分每个Button,所以我们在这里使用闭包:
private void FindChildrenWidgets<T>() where T : UIBehaviour
{
T[] widgets = GetComponentsInChildren<T>();
for (int i = 0; i < widgets.Length; i++)
{
string objName = widgets[i].gameObject.name;
if (widgets[i] is Button)
{
(widgets[i] as Button).onClick.AddListener(() =>
{
//使用闭包调用objName变量。
//此处方法可以是一个虚方法用于子类重写。
//也可以是一个事件,委托。
OnClick(objName);
});
}
}
}
/// <summary>
/// 统一提供的点击事件接口,子类只需要重写此方法并使用switch判断名字即可实现不同按钮的点击事件
/// 所有的点击事件都在查找控件的时候就已经添加了
/// </summary>
/// <param name="name">按钮名字</param>
protected virtual void OnClick(string name)
{
}
这样就完美解决了使用一次循环完成多种事件添加情况。