C#for Unity3D:详解委托和事件

委托的概念和委托类型的声明

什么是委托

  • 委托是C#中由用户自定义的一个类型
  • 类表示的是数据和方法的集合,而委托实际上是一个能够持有对某个或某些方法的引用的类
  • 与其他类不同,委托类能拥有一个签名,并且它只能持有与它的签名相匹配的方法的引用

如何使用委托

  • 声明一个委托类型
  • 使用该委托类型声明一个委托变量
  • 创建委托类型的对象,把它赋值给委托变量,该委托对象包含某个方法的引用,这个方法和第一步定义的签名一致
  • 为委托对象增加其他方法
  • 像调用方法一样调用委托。此时,委托持有的每一个方法都会依次去执行

委托与类的相似之处

image.png

如何声明委托

image.png

  • 声明委托的语法与定义方法的语法类似,但没有方法体,声明的前面需要加关键字delegate
  • 声明委托相对于声明一个新类,所以可以在任何声明类的相同地方声明委托,可以在另一个类的内部声明,也可以在任何类的外部声明
  • 可以在委托的声明上应用任意常见的访问修饰符,如public,private等

创建委托对象

image.png

创建委托与声明委托代码

声明两个类,一个是普通类,一个是静态类
image.pngimage.png

创建委托,以及委托对象,让委托对象引用普通类和静态类中的方法:

image.png

委托的调用和委托数组

创建对象的赋值

image.png

委托的调用

image.png

委托数组

image.png

委托上方法的添加和移除

组合委托

image.png

image.png
同时也可以覆盖引用:

image.png

为委托添加方法

image.png

image.png

从委托中移除方法

image.png

委托的添加与删除测试

image.png

带返回值的委托以及调用

带返回值没有带参数的委托

声明带有返回值方法的普通类
image.png
声明带有返回值的委托
image.png
带有返回值的委托引用拥有返回值的方法
image.png

返回值的结果返回的都是最后一个方法返回的值。

image.png

带返回值并且带参数的委托

创建带有返回值的方法:

image.png
创建带有返回值的委托,并且委托带有参数:
image.png
调用带有返回值并且有参数的委托:

image.png

最终的结果为9,因为在执行自增的方法,虽然返回的结果是11,但是因为是值类型,外部num的值并没有改变,依旧是10,下次调用自减的方法传递的参数还是10,所以最终结果为9。如果你需要结果为10的话,就需要设置引用参数,使用引用参数方法改变了值,外部num就能接受到新的结果值,这时候要使用ref关键字来实现:同时委托里面也要声明ref关键字的参数,如下:

image.png

调用多播委托的异常处理

多播委托

image.png

声明异常类,在方法中抛出异常:

image.png

声明测试异常的委托
image.png
调用测试异常的委托
image.png

获取委托所引用的方法数组:(获取调用列表)
优化后,可以不会因为某一个方法抛出异常而不执行下次调用方法列表的调用:

image.png

匿名方法(一)

image.png

声明带有返回值并带有参数的委托
image.png

委托中,匿名方法的使用

image.png

匿名方法(二)

image.png
params关键字的作用:在编译代码的时候,C#看到params关键字,会自动将后面的变量值存储在当前声明params的变量里面。如下:

image.png
调用

image.png

扩展到如何使用委托来关联params呢

image.png

在声明委托对象的等号右边是不需要进行书写params的,只要在声明委托的时候带上params即可。
image.png

匿名方法(三)

image.png

Lambda表达式

匿名方法简化
image.png
Lambda表达式可以对匿名方法进行简化:

image.png

image.png

如果匿名方法没有参数(也就是委托没有参数的时候),则必须使用空的花括号
image.png

C#官方提供的委托

Action(16种)

使用Action的委托,C#内部还是自己声明的delegate类型的委托,唯一区别就是这个是C#是官方提供的,上面的委托是我们自己开发者定义的委托。

优点:开发者可以使用内置的Action委托,不用单独的定义委托。
缺点:使用Action不能有返回值,并且参数个数不超过16个,同时声明的参数类型需一致。

image.png

Func委托(17种==》16种参数类型+1种返回值类型)

优点:与Action相比,Func支持有返回值,并且参数类型不限制,可以编写多种不同的数据类型

对泛型(在这里是对Student类型进行排序)

创建student类

image.png

进行冒泡排序(第一个参数是需要比较的类型数组,第二个参数就是一个委托,也就是Func委托,前两个T表示泛型参数,可以接收任意两个参数,委托的返回值是int类型),在这里委托相当于作为了方法的参数,当调用BubbleSort()方法的时候,委托类型可以接收一个委托,而委托funAge引用了方法,会自动调用引用的方法。

image.png

在这里是针对学生类型的年龄进行从大到小排序,非常的妙!
image.png

Predicate委托

返回的只能是bool值,主要作为判断(某些)来处理。
image.png
参数介绍:

image.png

案例:实现1-100,所有的偶数打印
定义判断偶数方法逻辑:

image.png

方法接收起始值,结束值,以及需要的约束条件(也就是偶数的条件)
image.png

image.png

案例:实现所有学生年龄大于25岁的学生信息

image.png

事件

image.png
当事件触发的时候,会执行发布者,发布者会找到多个订阅者,然后回调执行这些订阅者上的方法(也就是订阅者对方法的引用,拥有了调用方法的权力)
image.png

四种主体的介绍:

image.png

事件与委托的关系

在C#中,如果声明了一个事件,那么在代码运行的时候,事件内部一定会产生一个私有的委托。
事件提供了对其私有委托的结构化范文,也就是编程者一定不能越过事件而去访问事件中的内部委托,因为它是私有的。要想操作的内部的私有委托,我们只能通过事件这样的封装去操作,这样的访问叫做结构化访问。我们可以看见事件和委托的关系就相当于普通类中属性对字段的封装一样,属性对字段封装后,我们也不能直接对字段进行访问,但是我们可以通过属性对于这个子弹的值进行修改或访问。

image.png

事件代码的五大组件:

image.png

image.png

事件代码的编写

声明茶叶委托类
image.png

订阅者提供事件处理程序(也就是回调函数)
image.png

事件的声明

image.png
在发布者类声明事件:

image.png

事件声明的注意事项

事件成员

image.png

订阅事件

image.png

image.png“发布者定义的事件+=回调方法”

触发事件

image.png

一般触发事件是写在发布者类当中,

image.png

image.png

EventHandler标准事件

EventHandler的参数类型是TeaEventArgs,后续在回调函数里面可以进行接收。
image.png

image.png

声明派生自EventArgs的类:

image.png

回调函数就可以接收了:(this执行的是本身,也就是发布者)

image.png

触发事件:

image.png

image.png

总结:只要我们需要传送数据,我们就需要创建一个数据类,里面包含了需要传递的数据,并且这个类是继承EventArgs的。然后再声明委托的时候,需要把数据类作为委托的参数,在尖括号里面进行编写。其次在整个的传递过程中,在订阅者里面,也就是那个回调方法里面可以进行接收数据类,里面可以获取到多个你定义的数据信息。这时候万事俱备,可以发布事件了,发布事件里面有两个类型,一个是发布者,另一个是传递的数据类。

事件的显示声明和隐式声明

在之前说过,事件是对委托的封装,我们只能在事件上进行注册和移除这两个操作。

如果我们在一个类的内部,声明一个事件成员,而声明的格式就如下:我们把这种声明方式叫做隐式声明。如果对一个事件进行隐式声明,那么C#在编译到声明这句话的时候就会按照事件是对委托的封装,每个事件内部都有一个私有的委托,编译器会在greetingEvent内部生成一个我们看不到的私有委托,而这个私有委托的名字和这个事件的名字是一模一样的。
image.png

所以之所以在一个类的内部我们可以实现对事件的赋值以及虽然是事件,但是依然能够使用委托的方式调用来调用事件。是因为我们在类的内部改动实际上是对私有化的内部改动,这种方式是可取的
image.png

。但是一旦跳出类的外部,外部的类是无法访问私有的委托的。也就是下面这种情况:

image.png

在类的外部进行访问私有委托,这时候编辑器会把它当做事件成员来看,所以对事件我们是不能进行赋值操作的,也不可以直接传参调用的。

总结的来说,对于一个委托对象来说,可以+=,也可以-=,也可以进行=初始化,也可以直接传参进行调用。但是对于事件来说,只允许两种操作,也就是+=,-=(注册、移除)

显示声明

一旦我们使用显示声明的方式,用add,remove语句,那么C#在编译的时候,就不会自动的默认生成同名的私有委托,它就会按照我们自己写好的add,remove语句(类似属性对字段的封装一样)。这时候对事件就不能赋值

image.png

image.png

显示声明和隐式声明在不同场景中都会用到,需要明白它们之间的区别,并且要理解它们分别对事件的操作和委托的操作所允许的方式是不一样的。对事件只允许+=,-=,而对委托可以进行=初始化,以及传参数调用它。

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYFHoSja' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片