Skip to content

delegate

csharp-delegate-deep-dive

delegate 是什么

delegate 是“方法类型”。普通变量保存数据,delegate 变量保存方法。

c
public delegate void DamageHandler(int damage);

这句话的意思是:我定义了一种方法形状,它必须:

c
返回 void
参数是 int

所以这种方法可以赋给它:

c
void ShowDamage(int damage)
{
    Debug.Log($"受伤:{damage}");
}

最小完整例子

c
public delegate void DamageHandler(int damage);

DamageHandler onDamaged;

void Start()
{
    onDamaged = ShowDamage;
    onDamaged += PlaySound;

    onDamaged?.Invoke(10);
}

void ShowDamage(int damage)
{
    Debug.Log($"飘字:-{damage}");
}

void PlaySound(int damage)
{
    Debug.Log("播放受伤音效");
}

+= 是添加一个方法。 -= 是移除一个方法。 ?.Invoke() 是安全调用,防止没有订阅者时报空引用。

Action 和 Func

很多时候不用自己写 delegate,直接用系统内置的:

c
Action<int> onDamaged;          // 无返回值,参数 int
Func<int, bool> isDeadChecker;  // 参数 int,返回 bool

记法:

c
Action:只做事,不返回结果
Func:做完后返回结果,最后一个泛型类型是返回值

event 是什么

event 可以理解成“受保护的 delegate”。外部只能订阅和取消订阅,不能随便触发。

c
public event Action<int> OnDamaged;

public void TakeDamage(int damage)
{
    OnDamaged?.Invoke(damage);
}

监听方:

c
void OnEnable()
{
    player.OnDamaged += RefreshHpUI;
}

void OnDisable()
{
    player.OnDamaged -= RefreshHpUI;
}

Unity 里常见模式就是:OnEnable 订阅,OnDisable 取消订阅。

常见坑

签名必须匹配,参数和返回值对不上就不能赋值。 委托可能是 null,调用前用 ?.Invoke()。 匿名 lambda 不好取消订阅,需要取消时最好保存成变量。 event 更适合公开“某件事发生了”的通知,普通 delegate 更适合内部回调或策略传递。

参考链接Microsoft C# Delegatesdelegate 关键字Microsoft ActionMicrosoft FuncMicrosoft EventsUnity UnityEvent

文章评价

读完这篇,留下你的看法

暂无审核通过的评价。

登录账号后才能评价。

本站访客数0总站访问量0本页访问量0