第三十六式:C# 事件 (穿云箭)

绝世
秘籍
一支穿云箭,千军万马来相见。
当江湖上发生大事(比如教主遇袭),需要通知各方豪杰采取行动。
这在 C# 中就是事件 (Event)
这和委托(Delegate)有什么区别?
委托是谁都能调用(可以乱发号施令)。
事件则是一种受保护的委托,只有教主(定义事件的类)才能发射信号,其他人只能订阅 (Subscribe)(听令)。

1. 定义事件 - 设立烽火台


class SectLeader
{
    // 定义一个委托
    public delegate void Notify();
    
    // 基于委托定义事件
    public event Notify OnAttack;

    // 发射信号!
    public void BeAttacked()
    {
        Console.WriteLine("教主:我被打了!");
        if (OnAttack != null) // 如果有人在听
        {
            OnAttack(); // 触发事件
        }
    }
}
        

2. 订阅事件 - 听候差遣

使用 += 来订阅,使用 -= 来取消订阅。


class Disciple
{
    public void Fight()
    {
        Console.WriteLine("弟子:护驾!");
    }
}

// Main:
SectLeader dongfang = new SectLeader();
Disciple yang = new Disciple();

// 1. 订阅:杨莲亭发誓要保护东方不败
dongfang.OnAttack += yang.Fight;

// 2. 触发:教主被打
dongfang.BeAttacked(); 
// 输出:
// 教主:我被打了!
// 弟子:护驾!
        
这是 GUI 编程(比如按钮点击)的核心!
你点击按钮,按钮触发 Click 事件,你的代码订阅了这个事件,然后执行逻辑。
切记:外部类只能订阅/取消订阅,绝不能直接触发事件(不能写 dongfang.OnAttack()),那是越权!
🎆

动手时刻:闹钟

创建一个 Clock 类,有一个 OnAlarm 事件。

当调用 Ring() 方法时,触发该事件。

在 Main 里订阅它,输出“起床练功了!”。

查看参考答案

class Clock
{
    public event Action OnAlarm; // 用系统自带的 Action 委托更省事

    public void Ring()
    {
        if (OnAlarm != null) OnAlarm();
    }
}

// Main:
Clock c = new Clock();
c.OnAlarm += () => Console.WriteLine("起床练功!"); // Lambda 写法
c.Ring();
                    

成就解锁:【号令群雄】 获得:盟主令