事件:发布/订阅与 event 关键字
使用事件实现发布/订阅:声明事件、添加/移除处理程序,通过 EventArgs 传递数据,并按照 OnX 模式触发事件。
事件:发布/订阅与 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 关键字的作用
总结
总结:声明一个事件,让监听器进行附加或分离,使用 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 反馈 — 无需本地设置。
此课程中的所有课时
- delegate、Action/Func 与闭包
- 事件:发布/订阅与 event 关键字
- 事件模式与常见陷阱(内存泄漏)