Unity/C#知识点 -- Lambda表达式、委托Delegate、事件Event、Action、Func、UnityAction、UnityEvent综述

Lambda表达式

Lambda表达式本质上就是定义匿名函数

1 Lamba表达式基本结构

(形参列表) => {函数体};   // 当形参只有一个时可以省去"()", 当函数体内只有一段语句时可以省去"{}"

2 将函数改写为Lambda表达式

2.1 无返回值无参数时

void Func1()
{
	Debug.Log("Func1 call");
}
// Lambda表达式:
() => {Debug.Log("Func1 call");Debug.Log("Func100 call");};
() => Debug.Log("Func1 call");   // 如果匿名函数内部只有一段话,可以省去"{}"

2.2 有参数无返回值时

void Func2(int a)
{
    a *= a;
    Debug.Log(a);
}
// Lambda表达式:
(a) => {a *= a; Debug.Log(a);};
a => {a *= a; Debug.Log(a);};

2.3 有返回值有参数时

int Func3(int a, int b)
{
    return a + b;
}
// Lambda表达式
int res = (a, b) => {return a + b;};  // 存在返回值时不可以省略"{}"

委托Delegate

委托可以理解为存储方法的数组,通过委托可以将几个具有相同形参类型和返回值类型的方法加入到一个委托中一并执行

1 定义委托

private int delegate VoidDelegate(int a, int b);   // 括号内为传递的参数

2 实例化委托

VoidDelegate d1; 
VOidDelegate d1 = new VoidDelegate(Func1);   // 如果利用new关键字定义委托,同时需要为其赋初值

3 向委托中添加/删除函数

d1 = Func1;    // 添加第一个函数时需要直接赋值
d1 += Func2;   // 注意这里只能传递一个函数名进去,如果函数名后面加了括号,就会执行该函数一次,这是我们不期望的
d1 += Func3;   
d1 -= Func1;

4 调用委托

d1();    // 直接调用
d1.Invoke(a, b)   // 利用Invoke调用

完整代码

public delegate int IntDelegate(int a, int b);
private void IntDelegateTest()
{
    IntDelegate id;
    id = (a, b) => { return a + b; };
    id += (a, b) => { return a - b; };
    id += (a, b) => { return a * b; };
    int res = id.Invoke(1, 2);   // int res = id(1, 2);
    Debug.Log(res);
}
// 返回值为2,当委托存在返回值时,就只会返回最后加进去的函数的返回值

输出结果:
在这里插入图片描述

委托的使用类内和类外无差别

事件Event

事件可以理解为委托的一个实例(不太严谨),在类的内部声明事件,必须先声明该事件对应的委托类型

同时事件不仅可以添加函数进去,还可以加入委托

public delegate void VoidDelgate(int a);
public static event VoidDelgate voidEvent;
private void VoidEventTest()
{
    // 先定义一个委托
    VoidDelgate vd;
    vd = a => Debug.Log(a);
    vd += a => Debug.Log(a * a);

    // 向事件内添加委托和函数
    voidEvent = vd;
    voidEvent += a => Debug.Log(a - 1);
    voidEvent += a => Debug.Log(a + 1);
    voidEvent(6);
}

输出结果:

在这里插入图片描述

事件与委托的区别:

  • 委托创建时会定义方法的类型(是否有无参数、有无返回值)
  • 事件的创建需要一个委托才能声明(因为事件就是委托的实例)
  • 委托可以在任何类中或类外声明,但是事件只能在类中声明(类型跟实例,实例要运行所以要在类里面咯)
  • 事件只能在当前声明的类中调用,但是可以在其他类中为其添加/删除函数,无论将事件设置成public还是static其他类都无法调用

Action

Action可以理解为系统定义好的带泛型的delegate,Action是无返回值的

要使用Action需要引用头文件

using System;

Action的泛型T代表参数,T内可以传多个参数

private void ActionTest()
{
    Action action;   // 无参的Action
    action = () => Debug.Log("action use once");
    action += () => Debug.Log("action use twice");
    action();

    Action<int, string> action2;   // 有多个参数的Action
    action2 = (a, b) => Debug.Log("name: " + b + "\tage: " + a.ToString());
    action2 += (a, b) => Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    action2(18, "Ousun");
}

输出结果:
在这里插入图片描述

Func

Func可以理解为系统定义好的带泛型的delegate,Func是有返回值的

要使用Func需要引用头文件

using System;

Func<T,K>的前n-1个泛型代表参数, 最后一个泛型代表返回值类型

private void FuncTest()
{
    Func<int, int> func;
    func = (a) => { Debug.Log(a); return a; };
    func += (a) => { a += 1; Debug.Log(a); return a; };
    func += (a) => { a += 2; Debug.Log(a); return a; };
    int res = func(1);
    Debug.Log("res = " + res.ToString());
}

输出结果:
在这里插入图片描述

UnityAction

UnityAction是Unity对C#中Action的再封装,是更适合再Unity中使用的一种泛型委托,用法和Action一样

需要包含头文件:

using UnityEngine.Events;
private void UnityActionTest()
{
    UnityAction action;   // 无参的Action
    action = () => Debug.Log("action use once");
    action += () => Debug.Log("action use twice");
    action();

    UnityAction<int, string> action2;   // 有多个参数的Action
    action2 = (a, b) => Debug.Log("name: " + b + "\tage: " + a.ToString());
    action2 += (a, b) => Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    action2(18, "Ousun");
}

输出结果:

在这里插入图片描述

UnityEvent

UnityEvent可以在面板中添加监听事件,也可以在代码中添加监听事件或UnityAction

public UnityEvent<int, string> myEvent;

UGUI中的Buttom点击事件,就继承自UnityEvent,可以将UnityEvent显示在监视器面板中
在这里插入图片描述

在代码中调用event,只能使用Invoke方法调用,同时,UnityEvent内添加的方法可以是UnityAction

用 AddListener 和 RemoveListener 分别为事件添加和移除方法

public UnityEvent<int, string> myEvent;
private void UnityEventTest()
{
    myEvent.AddListener((a, b) => 
    { 
    	Debug.Log("name: " + b + "\tage: " + a.ToString()); 
    });
    myEvent.AddListener((a, b) =>
    {
    	Debug.Log("name: " + b + "\tage: " + (a + 1).ToString());
    });
    myEvent.Invoke(18, "Ousun");
}

输出结果:

在这里插入图片描述

配合监视器面板使用:

监视器如下:

在这里插入图片描述

添加的相关函数如下:

public void InspectorEvent(int a, string b)
{
	Debug.Log("InspectorEvent is called");
}

public void InspectorEvent2(int a, string b)
{
	Debug.Log("InspectorEvent2 is called");
}

再次调用上面的UnityEventTest()函数,输出结果如下:

在这里插入图片描述
参考:【Unity知识点】通俗解释delegate,事件event,Action,Func和UnityAction,UnityEvent

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值