【Unity|C#】基础篇(8)——委托(Delegate)/ 事件(Event)
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了【Unity|C#】基础篇(8)——委托(Delegate)/ 事件(Event),小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含4811字,纯文字阅读大概需要7分钟。
内容图文

【学习资料】
> 在线文档
官方文档:https://docs.microsoft.com/zh-cn/dotnet/csharp/
菜鸟教程(高级教程):https://www.runoob.com/csharp/csharp-tutorial.html
> 视频教程
腾讯学院、Siki学院
> 书籍
《C#图解教程》(第13~14章):https://www.cnblogs.com/moonache/p/7687551.html
【学习内容】
> 菜鸟教程:高级教程部分(委托、事件)
> 《C#图解教程》:第13~14章
> 委托与事件详解Part1:http://www.tracefact.net/tech/009.html
> 委托与事件详解Part2:http://www.tracefact.net/tech/029.html
【委托Delegate】
-
定义
- 类似C++的函数指针,delegate相当于是 指向某对象的某个函数,的 引用类型变量
-
委托和类一样,也需要 声明、创建、赋值
- 声明委托类型(像类一样声明一个委托类型) publicdelegate [函数返回值] 委托名称(参数1,参数2...);
- 创建委托变量 MyDelegate opt = new MyDelegate(AddNum); (实际绑定的是:this.AddNum)
-
重新赋值 opt = MultNum; (实际绑定的是:this.MultNum)
- 执行委托:就是执行引用的 委托函数
- 委托可以:动态修改引用的函数
-
// 声明:一个可以指向 返回类型为int,带2个int参数的 函数 public delegate int MyDelegate(int a, int b); // 相加函数publicint AddNum(int a, int b) { return (a + b); } // 相乘函数publicint MultNum(int a, int b) { return (a * b); } void Start() { // 创建:指向不同函数的委托类型 MyDelegate opt = new MyDelegate(AddNum); Debug.Log(opt(2, 5)); // 执行委托函数: 7 // 运行时,可以改变赋值 opt = MultNum; Debug.Log(opt(2, 5)); // 执行委托函数: 10 }
-
委托多播
- 创建的委托类型变量 opt 可以存储 函数调用列表(绑定多个委托函数)
-
通过 "+",或"+=":添加 一个函数引用
- 通过 "-",或"-=" :移除 某个函数的引用
- 执行委托:会执行所有添加绑定的 委托函数
-
public delegate void MyDelegate(int a, int b); // 输出相加结果publicvoid PrintAddNum(int a, int b) { Debug.Log("PrintAddNum:" + (a + b)); } // 输出相乘结构publicvoid PrintMultNum(int a, int b) { Debug.Log("PrintMultNum:" + (a * b)); } void Start() { // 创建:指向不同函数的委托类型 MyDelegate opt = new MyDelegate(PrintAddNum); // 通过+=添加委托函数 // 也可以直接相加 opt = PrintAddNum + PrintMultNum; opt += PrintMultNum; // 执行委托,会按添加的顺序,分别执行PrintAddNum和PrintMultNum opt(2, 5); // 通过-=移除对某函数的引用 opt -= PrintAddNum; // 再次执行委托,只执行了PrintMultNum opt(2, 5); } // 输出 // PrintAddNum: 7 // PrintMultNum: 10 // PrintMultNum: 10
-
委托绑定函数及执行原理
-
绑定委托函数
- 可以通过:“=”、“+=”、“-=”、“+”、“-”,来重新给委托绑定函数,或添加删除函数
- 绑定普通函数:同时会将对象(this)引用存储起来
- 绑定静态函数:无需存储对象(this)引用
-
class Person { public delegate void MyDelegate(int a, int b); public MyDelegate myDelegate; // 普通函数,绑定时需要有明确对象(this)publicvoid Func1(int a, int b) { ... } // 静态函数,通过类名.Func2绑定publicstaticvoid Func2(int a, int b) { ... } } void Start() { Person myPerson = new Person(); //myPerson.myDelegate += Person.Func1; // 报错,Func1需要对象(this) myPerson.myDelegate += Person.Func2; myPerson.myDelegate += myPerson.Func1; //myPerson.myDelegate += myPerson.Func2; // 报错,Func2是静态函数 }
-
执行方式
- 通过"+" 或 "+=" 的顺序,依次执行绑定的委托函数
- 普通函数:相当于 调用 绑定对象引用(this)的函数,包含了对象的this引用
- 静态函数:相当于 调用 绑定的委托函数;
-
// 声明委托类型 public delegate void MyDelegate(); class Person { public string name; public void PrintName() { Debug.Log(name); } } void Start() { // 创建2个对象 Person myPerson = new Person(); Person myPerson2 = new Person(); myPerson.name = "Alice"; myPerson2.name = "Bob"; // 创建委托变量 MyDelegate myDelegate = new MyDelegate(myPerson.PrintName); // 多播:委托函数 myDelegate += myPerson2.PrintName; // 执行委托 myDelegate(); } // 输出 // Alice // Bob
-
绑定委托函数
【事件】
-
定义
- 事件是对委托的封装,关系和字段与属性(Property) 一样
- 事件是基于委托,所以首先要声明委托,再定义事件
// 声明委托类型publicdelegatevoid MyDelegate(int a, int b); // 定义事件publicevent MyDelegate myEvent;
- 原理
- 实际上与属性一样,定义一个事件,会自动创建一个隐藏(private)的委托类型变量
- 并包含了add_xxx("+=")和remove_xxx("-="),用来添加/删除 委托函数
- 事件的执行:只能在定义事件的类内部执行
// 声明委托类型publicdelegatevoid MyDelegate(int a, int b); class Person { // 定义事件publicevent MyDelegate myEvent; publicvoid FireEvent(int a, int b) { if (myEvent != null) myEvent(a, b); // 必须在定义事件的类内部执行 } } publicvoid PrintAddNum(int a, int b) { Debug.Log("PrintAddNum:" + (a + b)); } publicvoid PrintMultNum(int a, int b) { Debug.Log("PrintMultNum:" + (a * b)); } void Start() { Person person = new Person(); person.myEvent += PrintAddNum; person.myEvent += PrintMultNum; //person.myEvent(2, 5); // 报错,无法在定义事件的类外部执行 person.FireEvent(2, 5); // 正确 }
- 注:事件不能在类的外部使用赋值“=”,但是在类内部可以重新赋值“=”
- 事件与委托一样,也支持多播:可以通过“+=”、“-=” 来添加事件、删除事件
- 事件访问器(add / remove)
- 事件与委托的关系,与 字段与属性的关系是一样的,所以也有访问器
- 关键字: add remove
publicevent MyDelegate myEvent { add { ... //执行 += 运算符的代码 } remove { ... //执行 -= 运算符的代码 } }
-
为什么使用事件?
-
对委托的封装
- 对外只能通过事件来 添加/删除 绑定的委托函数
- 事件只能在定义事件的 类内部执行
- 满足观察者模式(发布者-订阅者)
-
当然不使用事件,也可以实现对委托的封装
- 将委托定义为private,然后对外提供添加/删除委托函数的方法(相当于手动实现事件中的add_xxx和remove_xxx)
-
// 声明委托类型 public delegate void MyDelegate(int a, int b); class Person { // 定义一个私有委托变量public MyDelegate myDelegate; // 添加publicvoid AddEvent(MyDelegate d) { myDelegate += d; } // 删除publicvoid RemoveEvent(MyDelegate d) { myDelegate -= d; } // 执行publicvoid FireEvent(int a, int b) { if (myDelegate != null) myDelegate(a, b); // 必须在定义事件的类内部执行 } } publicvoid PrintAddNum(int a, int b) { Debug.Log("PrintAddNum:" + (a + b)); } publicvoid PrintMultNum(int a, int b) { Debug.Log("PrintMultNum:" + (a * b)); } void Start() { Person person = new Person(); person.AddEvent(PrintAddNum); // this.PrintAddNum person.RemoveEvent(PrintMultNum); // this.PrintMultNum person.FireEvent(2, 5); }
-
对委托的封装
原文:https://www.cnblogs.com/shahdza/p/12239296.html
内容总结
以上是互联网集市为您收集整理的【Unity|C#】基础篇(8)——委托(Delegate)/ 事件(Event)全部内容,希望文章能够帮你解决【Unity|C#】基础篇(8)——委托(Delegate)/ 事件(Event)所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。