目录

事件(event)是什么?它和委托是什么关系?

一句话总结:

事件是一种特殊的委托,专用于“发布–订阅”模式,让外部只能订阅/取消订阅,而不能随便触发事件。

换句话说:

  • 委托 = “能指向方法的变量”
  • 事件(event) = “一个用来广播消息的委托,但加了限制,只允许 += 和 -=”

一、为什么要有事件?直接用委托不行吗?

看这个例子:

public class Button
{
    public Action OnClick; // 这是一个委托
}

然后外部能这样玩:

button.OnClick = null;        // 外部把监听者全部干掉
button.OnClick();             // 外部强制触发事件
button.OnClick = HackMethod;  // 全部替换掉

这样非常危险。

二、事件解决了这些问题

把上面的代码改成事件:

public class Button
{
    public event Action OnClick;
}

现在外部 只能做两件事

button.OnClick += SomeMethod; // 订阅
button.OnClick -= SomeMethod; // 取消订阅

外部不能:

button.OnClick();      // ❌ 不能触发
button.OnClick = null; // ❌ 不能替换
button.OnClick = xxx;  // ❌ 不能赋值

只有 Button 内部才能触发事件:

OnClick?.Invoke();

三、事件的完整使用流程

1)定义事件(必须在类内部)

public event Action SomethingHappened;

2)订阅事件

obj.SomethingHappened += OnSomething;

3)触发事件(只能类内部触发)

SomethingHappened?.Invoke();

4)事件响应函数

void OnSomething()
{
    Console.WriteLine("事件触发了");
}

四、事件为什么经常配合委托?

因为事件其实就是把委托包装了一层访问限制。

你可以把事件理解为:

public delegate void ClickHandler();

private ClickHandler _click;

public event ClickHandler Click
{
    add { _click += value; }
    remove { _click -= value; }
}

也就是说:

事件 = 内部维护一个委托 + 限制外部只能订阅/取消


五、一个简单例子:广播通知

public class Alarm
{
    public event Action OnAlarm; // 定义事件

    public void Trigger()
    {
        Console.WriteLine("警报触发!");
        OnAlarm?.Invoke();       // 触发
    }
}

外部:

var alarm = new Alarm();
alarm.OnAlarm += () => Console.WriteLine("听到警报,开始撤离!");
alarm.Trigger();

执行结果:

警报触发!
听到警报,开始撤离!

六、总结

项目 委托 事件

本质 方法的变量 委托的包装

用途 回调,传方法 发布–订阅

外部能触发吗? ✔ 可以 ❌ 不可以

外部能赋值替换吗? ✔ 可以 ❌ 不可以

外部能 +=/-= 吗? ✔ 可以 ✔ 可以