Unity委托详解

委托(Delegate)及Action/Func区别与联系

示例代码放在最后,可以先去看一眼完整代码,前面会依次详细分析哒

1.delegate关键字

1
public delegate int Handler(string msg);

委托实际上可以看做函数指针列表或者函数清单,满足条件的函数(参数、返回值)可以统统加入这个清单,当激活这个委托时会逐条执行委托清单中的所有函数,并返回最后一个函数的返回值。

  1. delegate关键字后面的内容可以看做是函数模板,请写好你的参数列表和返回值
  2. 编译器会将delegate编译为一个继承自MulticastDelegate的类,如下图
    生成的Handler类
  • 生成的类包含有析构函数和三个虚函数
  • Invoke/EndInvoke 的返回值就是前面函数模板规定的返回值
  • BeginInvoke/EndInvoke 成对出现,用于异步编程
  • 这里的继承关系是 Handler:MulticastDelegate:Delegate
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    public static Handler handler1;

    void Start()
    {
    handler1 += MyFunction;
    handler1.Invoke("Hello World!");
    }

    int MyFunction(string msg)
    {
    return 0;
    }
  1. 使用方法也很简单了,声明一个刚才定义的委托,然后把对应函数添加到委托清单即可
  2. 这里 += -= 运算符实际上是Delegate类中Combine/Remove方法,用于将函数添加/移出委托清单

2.Action类与Func类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static Action<string> action1;
public static Func<string, int> func1;

void Start()
{
action1 += MyVoidFunction;
func1 += MyFunction;
action1.Invoke("Hello World!");
func1.Invoke("Hello World!");
}

int MyFunction(string msg)
{
return 0;
}

void MyVoidFunction(string msg)
{
return;
}
  1. 这俩家伙都是MulticastDelegate的派生类,相当于包装了一层,免去你自己定义委托的麻烦,使用方法和直接用委托无异
  2. 区别是Func有返回值,返回类型就是声明时写在最后的类型

3.event关键字

1
2
3
public static event Handler handler2;
public static event Action<string> action2;
public static event Func<string, int> func2;
  1. event可以修饰Delegate类,实际上就是委托的特殊封装
  2. 编译后如下图,注意到访问修饰符变成了private,原因在后面
    访问修饰符变为private
    1
    2
    3
    4
    MyDelegate.handler1 = TestFunction;
    MyDelegate.handler1 += TestFunction;
    //MyDelegate.handler2 = TestFunction;
    MyDelegate.handler2 += TestFunction;
  3. 在其他类中去使用我们定义的委托,可以发现event修饰的委托不能直接赋值,正如我们前面说的,访问修饰符已经被改为private,这样做的好处是再也不会有人手滑直接赋值将函数清单清空
  4. 那为什么 += -= 运算符还能用呢?实际上是编译器在原来的类中生成了对应的方法,如下图
    编译生成方法
  • add_ remove_对应添加/删除
  • 方法里面还是调用Delegate类中Combine/Remove方法,就再不截图啦

4.示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
using System;
using UnityEngine;

public delegate int Handler(string msg);

public class MyDelegate : MonoBehaviour
{
public static Handler handler1;
public static Action<string> action1;
public static Func<string, int> func1;
public static event Handler handler2;
public static event Action<string> action2;
public static event Func<string, int> func2;

void Start()
{
handler1 += MyFunction;
handler2 += MyFunction;
action1 += MyVoidFunction;
action2 += MyVoidFunction;
func1 += MyFunction;
func2 += MyFunction;

handler1.Invoke("Hello World!");
handler2.Invoke("Hello World!");
action1.Invoke("Hello World!");
action2.Invoke("Hello World!");
func1.Invoke("Hello World!");
func2.Invoke("Hello World!");
}

int MyFunction(string msg)
{
return 0;
}

void MyVoidFunction(string msg)
{
return;
}
}

public class Test
{
private void Start()
{
MyDelegate.handler1 = TestFunction;
MyDelegate.handler1 += TestFunction;
MyDelegate.action1 = TestVoidFunction;
MyDelegate.action1 += TestVoidFunction;
MyDelegate.func1 = TestFunction;
MyDelegate.func1 += TestFunction;
//MyDelegate.handler2 = TestFunction;
MyDelegate.handler2 += TestFunction;
//MyDelegate.action2 = TestFunction;
MyDelegate.action2 += TestVoidFunction;
//MyDelegate.func2 = TestFunction;
MyDelegate.func2 += TestFunction;
}

private int TestFunction(string msg)
{
return 0;
}
private void TestVoidFunction(string msg)
{
return;
}
}

完结撒花~


Unity委托详解
https://baifabaiquan.cn/2023/11/25/unity委托详解/
作者
白发败犬
发布于
2023年11月25日
许可协议