C# Academy · 课时

事件:发布/订阅与 event 关键字

使用事件实现发布/订阅:声明事件、添加/移除处理程序,通过 EventArgs 传递数据,并按照 OnX 模式触发事件。

第 2 / 3 课8 个步骤

事件:发布/订阅与 event 关键字 是 CoddyKit 上的免费 C# Academy 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 C# Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 C# Academy 课程共包含 3 节课。

事件概览

目标:通过事件实现发布与订阅。

  • 在发布者上声明事件
  • 使用 += 订阅,使用 -= 取消订阅
  • 在发布者中安全地触发事件
  • 使用 EventArgs 传递数据

基本事件用法

公开一个事件,让监听器进行附加或分离。只有发布者可以调用它。

using System;

public class Button
{
  public event EventHandler Click;

  public void SimulateClick()
  {
    // Safe raise: copy then invoke if not null (C# 6-safe)
    EventHandler h = Click;
    if (h != null) h(this, EventArgs.Empty);
  }
}

public class Program
{
  static void OnClick(object sender, EventArgs e)
  {
    Console.WriteLine("Clicked!");
  }

  public static void Main(string[] args)
  {
    Button b = new Button();
    b.Click += OnClick;    // subscribe
    b.SimulateClick();     // prints "Clicked!"

    b.Click -= OnClick;    // unsubscribe
    b.SimulateClick();     // no output
  }
}

带数据的事件

使用 EventArgs(或 EventHandler<TEventArgs>)向订阅者传递有用的数据。

using System;

// Data for the event
public sealed class PriceChangedEventArgs : EventArgs
{
  public decimal OldPrice { get; private set; }
  public decimal NewPrice { get; private set; }
  public PriceChangedEventArgs(decimal oldP, decimal newP)
  {
    OldPrice = oldP; NewPrice = newP;
  }
}

public sealed class Product
{
  private decimal _price;
  public event EventHandler<PriceChangedEventArgs> PriceChanged;

  public decimal Price
  {
    get { return _price; }
    set
    {
      if (value != _price)
      {
        decimal old = _price;
        _price = value;
        EventHandler<PriceChangedEventArgs> h = PriceChanged;
        if (h != null) h(this, new PriceChangedEventArgs(old, _price));
      }
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Product p = new Product();
    p.PriceChanged += delegate(object s, PriceChangedEventArgs e)
    {
      Console.WriteLine("Price: " + e.OldPrice + " -> " + e.NewPrice);
    };
    p.Price = 10m;
    p.Price = 12m;
  }
}

多播与 lambda 表达式

事件支持多播:多个处理程序会按照订阅顺序运行。请使用命名处理程序或匿名处理程序。

using System;

public class Alarm
{
  public event EventHandler Ring;

  public void Trigger()
  {
    EventHandler h = Ring;
    if (h != null) h(this, EventArgs.Empty);
  }
}

public class Program
{
  static void HandlerA(object s, EventArgs e) { Console.WriteLine("A"); }
  static void HandlerB(object s, EventArgs e) { Console.WriteLine("B"); }

  public static void Main(string[] args)
  {
    Alarm a = new Alarm();
    a.Ring += HandlerA;                           // named
    a.Ring += delegate(object s, EventArgs e) { Console.WriteLine("lambda"); }; // anon
    a.Ring += HandlerB;

    a.Trigger(); // prints A, lambda, B (multicast order)
  }
}

OnX 触发模式

使用受保护的 OnX 方法来触发事件。将委托复制到局部变量,并在调用前检查其是否为 null。

using System;

public class Ticker
{
  public event EventHandler Tick;

  protected virtual void OnTick()
  {
    EventHandler h = Tick;          // copy to local
    if (h != null) h(this, EventArgs.Empty);
  }

  public void RunOnce()
  {
    // do work...
    OnTick(); // raise via protected method
  }
}

public class Program
{
  static void Show(object s, EventArgs e) { Console.WriteLine("Tick!"); }

  public static void Main(string[] args)
  {
    Ticker t = new Ticker();
    t.Tick += Show;
    t.RunOnce();
  }
}

事件提示与常见陷阱

提示:

  • 订阅者不再需要事件时,务必取消订阅( -= )。
  • 让处理程序保持简短;较长的工作应排入队列。
  • 使用 EventArgs(或其子类)传递数据。
  • 只有发布者应该触发事件。

event 关键字的作用

快速检查:哪个 C# 关键字公开委托以支持订阅和取消订阅,同时阻止外部代码直接调用它?

总结

总结:声明一个事件,让监听器进行附加或分离,使用 EventArgs 传递数据,并通过受保护的 OnX 方法触发事件。

免费开始

用 AI 导师学习 C# — 免费

在浏览器中编写并运行真实代码,获得全天候 AI 导师的即时帮助,并在网页或应用中继续学习。

课程
93
课程
346

常见问题解答

「事件:发布/订阅与 event 关键字」课时是免费的吗?

是的 — 「事件:发布/订阅与 event 关键字」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 C# Academy 课程的其余内容,请升级到 CoddyKit PRO。 C# Academy 课程共包含 3 节课。

「事件:发布/订阅与 event 关键字」这节课中我会学到什么?

使用事件实现发布/订阅:声明事件、添加/移除处理程序,通过 EventArgs 传递数据,并按照 OnX 模式触发事件。 你通过在浏览器中直接运行的动手代码来练习 C# Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 C# Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 C# Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。

「事件:发布/订阅与 event 关键字」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 C# Academy 课中编写并运行代码吗?

能。每节 C# Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. delegate、Action/Func 与闭包
  2. 事件:发布/订阅与 event 关键字
  3. 事件模式与常见陷阱(内存泄漏)
← 返回 C# Academy