【Unity】委托的初步介绍

【写在前面】
这篇总结是基于B站up主BeaverJoe的视频
另外这篇博客仅限于介绍、总结,基本是没有代码部分,而且代码实例也是看视频好理解

【委托•快餐篇】7分钟带你了解委托与Lambda表达式   https://www.bilibili.com/video/BV1H5411a7dc
【委托•预备篇】委托的一般使用介绍   https://www.bilibili.com/video/BV1U64y1F7c9/?spm_id_from=333.788.recommend_more_video.1
【委托•语法篇】委托类型的声明和实例以及Action委托和Func委托  https://www.bilibili.com/video/BV1Bk4y1B7DN/?spm_id_from=333.788.recommend_more_video.2

【委托基本概念与定义】
委托是事件以及Lambda表达式的基础,初步使用委托时,委托就像一个“集合了方法的方法”

委托是一种,委托可以指向一个或者多个方法(委托有参数列表和返回值)
我们可以理解为:委托是一个用于存储方法的容器,在需要的时候,我们可以通过调用这个委托来调用相应的方法。委托存储的方法需要类型兼容

类型兼容:方法的签名和返回值和委托的签名和返回值一致

委托类型的实例就可以代替这些方法,直接调用它们,以及间接调用它们各自的方法

委托类型的变量通过Invoke方法或者其他更简练的调用形式,来间接调用这些方法
利用+=把方法给到委托

【委托的声明】
[访问修饰符] [delegate关键字] [目标方法的访问值类型] [名字] (目标参数列表);
public delegate void MyDelegate();

上文的代码所写的委托,可以指向任意一个返回值为空,参数列表为空的方法

目标方法就是指委托要指向的方法,它们的签名和返回值都是一样的

我们发现委托的声明和方法很像,不过请记住,委托是一种类,这一点在后面会有所体现
我们通常把委托的声明放在其他类型之外,保持类之间的平级关系
不过委托的声明也是可以放在类的内部的(因为C#支持嵌套类型)

【创建委托实例】
我们之前说过这玩意是个类,下面说说怎么创建它的实例

1.在合适的地方声明委托 (public delegate void Mydelegate();)
2.创建委托类型的变量 (Mydelegate myDelegate ;)
3.创建实例,一般在OnEnable (myDelegate = new myDelegate(MethodA) ; )
4.调用委托(myDelegate.Invoke(); 直接写myDelegate();也是可以的)
5.继续使用委托,多播委托,添加方法(myDelegate += new Mydeleate(MethodB)),同样也可以直接写成 myDelegate += MethodB ;
(但这样的做法可能会导致内存泄漏、性能下降,之后需要通过事件、观察者模式来更好地优化它)

public delegate void Mydelegate();
Mydelegate myDelegate ;  //出于习惯这么写,实质上爱叫什么叫什么
myDelegate = new myDelegate(MethodA) ;  
myDelegate.Invoke();  //实质上直接写myDelegate();也是可以的  
myDelegate += new Mydeleate(MethodB) ;  //多播

另外,在创建实例的时候可以直接把方法给委托
myDelegate = MethodA ;

注意,在这里以及3.创建实例中的方法,是只写名字不加括号的。特别对于myDelegate = MethodA 而言,如果写成了myDelegate = MethodA(); 意思是调用了MethodA方法,而不是把这个方法给到myDelegate。这里我们需要把方法理解成“一个加入到委托中的东西”,而不是调用它

在C#中,有两个已经定义好了的委托:
Action委托:无返回值,但是可以有参数列表,最多指向16个参数类型的方法
Func委托:有返回值,也可以有参数列表

【在Unity中的使用委托】
在了解了委托之后,我们现在有两种途径来调用我们的方法:
直接调用:通过直接使用方法的调用
间接调用:通过委托进行方法的调用

委托好在它的间接调用以及委托本身是一种类,这两种属性结合,使我们可以利用以委托作为参数的方法,来间接调用想要用的方法,这种调用是动态调用。此外,类可以作为方法的参数类型

public delegate void MyDelegate();
Mydelegate myDelegate ; 

public void MainMethod (Mydelegate  _delegate){
	//
}

public void Method01(){
 	//
}

这么一来,我们在想使用方法的时候,就可以直接利用MainMethod(Method01); 调用

事实上,大多数情况下,我们是不需要声明一个自定义委托来供自己使用的,Action和Func可以运用与大多数情况,它们是泛型委托

【Action委托和Func委托的使用】
1.使用System

顺带一提,System和unityengine都含有Random,因此之后使用Random时就需要特别指定是谁的Random,如 System.Random……

2.Action action ; //因为Action已经内置,因此不需要重新public delegate 一个,这里我们直接生成Action委托的实例
3.如果是有参数列表的方法,则需要为Action具体化一个参数类型,比如
Action action ; 当有参数列表的时候,不要忘记在调用的时候写上
4.在方法中(一般是OnEnable方法)写上 action = new Action(…) 多播就之后+=

二者的使用与区别

Action委托,只能,且必须指向一个返回值为空的目标方法,对于参数列表无要求

Func委托,必须指向一个,有返回值的方法,参数列表无要求
Func使用时,<>内的最后一位是放回值的类型,前面的就是参数了
Func<double,double,double> func ; 最后一位代表返回值是double类型

一般来说Func是模板方法(用传回的参数来填补、执行方法)
Action是回调方法(动态选择是否要调用某方法)
模板方法和回调方法都是把委托作为参数传递到方法中的

posted @ 2021-05-07 08:48  RetenQ  阅读(410)  评论(0编辑  收藏  举报