1、Delegate普通委托:
- 如public delegate void MyDelegate();
public MyDelegate mydelegate; //需要实例化的,用的时候直接=赋值就可以了
2、事件:利用event声明,相对于普通的委托,拥有了2条限制
- 1)此委托无法被其他类直接调用
- 2)此委托无法通过=直接赋值,只能通过+=(订阅)和-=(取消订阅)方式赋值
3、Action和Func可以声明委托,并无需实例化
- 需要using System;
- public event Action myDelegate; //声明无返回值,无参数
- public event Action<T1, T2> myDelegate; //声明无返回值,有参数
- Func<int> myDelegate; //声明无返回值,int型参数
- Func<int, string, bool> myDelegate; //声明返回bool,int, string型参数
4、定义 public event EventHandler<AttackEventArgs> OnAttack;
//需要创建参数类等
public class AttackEventArgs : EventArgs
{
public Vector3 startPos;
public Vector3 endPos;
}
//调用委托
if(Input.GetMouseButton(0))
{
// ?.将会先判OnAttack是否为null
// invoke还没查
OnAttack?.Invoke(this, new AttackEventArgs{
startPos = transform.position,
endPos = Camera.main.ScreenToWorldPoint(Input.mousePosition)
});
}
//委托订阅
void Start()
{
playAttack.OnAttack += PlayerOrdinary;
}
//感觉和普通事件委托没啥区别。就是感觉是可以传一批数据,而且可以调用参数类的一些方法
private void PlayerOrdinary(object sender, PlayerAttack.AttackEventArgs e)
{
Debug.DrawLine(e.startPos, e.endPos);
// var newBullet = Instantiate(bullet, transform.position, Quaternion.identity);
Vector3 direction = (e.startPos - e.endPos).normalized;
}
闭包
Action[] actions = new Action[5];
for (var i = 0; i < actions.Length; i++) {
actions[i] = () => { Debug.Log(i); };
}
foreach (var item in actions) {
item();
}
这一段代码执行完结果为5,5,5,5,5
为什么?
闭包可以使其访问到其访问不到的变量。也就说其访问到了i,i在循环完后i=5;然后这5个委托都引用了这个i。所以打印的都是i
下一段代码
Action[] actions = new Action[5];
for (var i = 0; i < actions.Length; i++) {
int a = i; //栈中分配一个空间 值为 i的值
actions[i] = () => { Debug.Log(a); };
}
foreach (var item in actions) {
item();
}
这里打印出的是0,1,2,3,4。这5个分别引用了a。然后每次都给a进行了一次赋值
正常情况下,上面函数中变量在随着函数运行将会被释放除了那个数组。然而在闭包会造成C#为其生成一个类用于存储这些被引用的外部变量。因为类是引用类型所以会造成内存分配。
注意:要明确一点C# Lambda表达式使用局部变量是按引用传递的,E.g. 上面的打印全是5的原因
闭包造成的内存泄露
http://www.360doc.com/content/19/0402/14/22877383_825931106.shtml