一、委托
C#中委托有点类似一个函数指针,将限定类型的方法地址记录在字段中,可以向类一样的定义在外部,也可以定义在类中,在任意位置都可使用.Invoke()调用委托中存储的方法 ,同时通过委托,可以将方法作为参数在方法之间传递 同时微软和Unity都提供了一些定义好的委托,比如Action,EventHandler ,UnityAction 供开发者直接使用
具体使用如下
public delegate void Noioos(string a, int b);
public class Delegate_Test : MonoBehaviour
{
private Noioos noioos;
public void Start()
{
//将对应方法记录至noioos中
noioos += DoSomthing;
noioos += Delegate_2.DoSomthing;
//调用noioos中记录的所有方法
noioos.Invoke("aeiou", 7);
DoSomthing_Variant(DoSomthing);
DoSomthing_Variant((string a, int b) => { Debug.Log("无内鬼 "+b); });
}
public void DoSomthing(string a,int b)
{
Debug.Log($"a:{a},b:{b}");
}
//向方法中传入一个noioos类型的方法
public void DoSomthing_Variant(Noioos noioos)
{
noioos("脱裤子放屁", 1);
}
}
public class Delegate_2
{
static public void DoSomthing(string a, int b)
{
Debug.Log($"a2:{a+1},b2:{b+1}");
}
}
运行结果如下
二、事件
首先,在官方文档中事件的定义是LikeField,即像一个字段事件与委托的关系有点类似字段与属性
事件有自己完整的声明格式,包括 事件的添加移除,事件的处理器
完整声明格式如下
//事件的完整声明格式
//EventHandler是微软提供的一个返回值为 void 参数为object 和 EventArgs
private EventHandler noioosEventHandler;
public event EventHandler NoioosEventHandler
{
add
{
noioosEventHandler += value;
}
remove
{
noioosEventHandler += value;
}
}
同时在定义事件的类的外部 不能使用 = 重置委托列表,只能使用+= ,-=添加或移除处理器
简略的事件的声明格式是其实微软提供的一个语法糖,编译过程中会在后台自动生成一个委托类型的字段用来存储事件的各种处理器
2.顺便提一嘴
上面提到了EevntHabdler 这个委托类型
public delegate void EventHandler(object sender, EventArgs e);
就顺便说一嘴事件模型
事件模型包括了
事件的拥有者 Event Source 成田良悟
事件 Event 更新了无头骑士异闻录
事件的响应者 Event subscriber 你(sender)
事件处理器 Event Handler 根据更新内容(EventArgs)写5000字读后感
事件订阅 += operator 你订阅了该作者的无头骑士异闻录这个小说
使用这个类型的委托配合事件,可以很简单的完成这样一个模型
同时申明委托时,后缀加上handler来表示这个委托是用来记录对应事件处理器的如
public delegate void TouchMoveHandler (Vector3 delta);
public static event TouchMoveHandler TouchMoveEvent;
总结
事件是对于对于对应委托字段的一个封装(
阉割
),规定了只能在类内部调用以及重置委托列表
在外部只能使用+= -= 来添加或移除处理器(委托字段中记录的对应方法)
限制委托过于强大的功能来确保程序的正确性,比如避免在意料之外的地方调用委托,或者使用=,清空之前存储的所有方法