1. 委托(Delegate)
定义与作用
- 委托是类型安全的函数指针,用于封装方法,支持多播(链式调用)。
- 核心能力:将方法作为参数传递或异步回调。
使用场景
- 回调机制(如异步操作完成通知)。
- 实现策略模式(动态替换算法逻辑)。
- LINQ查询中的条件筛选(
Where(x => x > 6)
)。 - 多播委托(多个方法依次执行)。
示例代码
// 定义委托
public delegate void LogHandler(string message);
/ 使用委托public class Processor
{ public void RunTask(LogHandler logger)
{ logger("Task started.");
// ...业务逻辑 logger("Task completed.");
}
} // 调用方
var processor = new Processor();
processor.RunTask(message => Console.WriteLine($"[LOG] {message}"));
2. 事件(Event)
定义与作用
- 事件是基于委托的语法糖,强制封装性,遵循发布-订阅模式。
- 核心规则:只能在声明类内部触发(
Invoke
),外部仅能+=
或-=
订阅。
使用场景
- GUI事件(按钮点击、鼠标移动)。
- 观察者模式(状态变化通知)。
- 松耦合系统(组件间通信)。
示例代码
// 定义事件public class OrderService
{
public event EventHandler<OrderEventArgs> OrderSubmitted;
public void SubmitOrder(Order order)
{
// ...提交订单逻辑
OnOrderSubmitted(new OrderEventArgs(order));}
protected virtual void OnOrderSubmitted(OrderEventArgs e)
{ OrderSubmitted?.Invoke(this, e); } }
// 订阅事件 var service = new OrderService();service.OrderSubmitted += (sender, e) => {
Console.WriteLine($"Order {e.OrderId} submitted!");};
3. 委托与事件的关系
特性 | 委托 | 事件 |
---|---|---|
封装性 | 可被外部直接调用 | 只能在声明类内触发 |
多播 | 支持 | 支持 |
安全性 | 低(外部可修改委托链) | 高(外部仅订阅/取消) |
典型用途 | 灵活的方法传递 | 系统级通知(如UI交互) |
关键点总结
- 委托是基础:事件本质是受限的委托,编译器自动生成
add/remove
方法。 - 设计原则:
- 事件用于被动通知(如用户操作)。
- 委托用于主动传递逻辑(如回调函数)。
- 代码规范:事件命名使用
动词
(如Clicked
/DataReceived
),委托命名用Handler
后缀。
疑问与解决方案
Q1:为什么事件比委托更安全?
A1:事件禁止外部直接赋值(=
操作符),强制通过+=
和-=
管理订阅,避免覆盖其他订阅者。
Q2:何时选择自定义委托而非Action/Func
?
A2:需要明确语义时
(如public delegate void PriceChangedHandler(double oldPrice)
优于Action<double>
)。