模型:DeepSeek-R1,生成时间:2025 03-06 16:24
委托(Delegate)
本质:类型安全的函数指针(方法引用)
作用:定义方法签名,允许将方法作为参数传递
基础使用
// 1. 声明委托类型
public delegate void MyDelegate(string message);
class Program
{
// 2. 匹配委托签名的方法
static void ShowMessage(string msg)
{
Console.WriteLine($"Message: {msg}");
}
static void Main()
{
// 3. 实例化委托
MyDelegate del = new MyDelegate(ShowMessage);
// 4. 调用委托(会执行绑定的方法)
del("Hello Delegate!");
// 多播委托示例
del += AnotherMethod;
del("Multi-cast!");
}
static void AnotherMethod(string text)
{
Console.WriteLine($"Another: {text}");
}
}
委托特点:
- 类型安全:必须匹配方法签名(参数和返回类型)
- 多播能力:通过
+=
添加多个方法 - 异步调用:BeginInvoke/EndInvoke(注意:.NET Core 后已不再推荐)
事件(Event)
本质:基于委托的封装,实现发布-订阅模式
作用:提供类型安全的通知机制
标准事件模式
// 发布者类
public class TemperatureMonitor
{
// 1. 声明事件(基于 EventHandler 委托)
public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged;
// 2. 触发事件的方法
private void OnTemperatureChanged(float newTemp)
{
var handlers = TemperatureChanged;
handlers?.Invoke(this, new TemperatureChangedEventArgs(newTemp));
}
// 模拟温度变化
public void SimulateTemperatureChange(float temp)
{
Console.WriteLine($"Temperature updated: {temp}C");
OnTemperatureChanged(temp);
}
}
// 自定义事件参数
public class TemperatureChangedEventArgs : EventArgs
{
public float NewTemperature { get; }
public TemperatureChangedEventArgs(float temp)
{
NewTemperature = temp;
}
}
// 订阅者类
public class AlertSystem
{
public void Subscribe(TemperatureMonitor monitor)
{
monitor.TemperatureChanged += HandleTemperatureChange;
}
private void HandleTemperatureChange(object sender, TemperatureChangedEventArgs e)
{
if (e.NewTemperature > 30)
{
Console.WriteLine($"ALERT: High temperature ({e.NewTemperature}C)!");
}
}
}
// 使用示例
class Program
{
static void Main()
{
var monitor = new TemperatureMonitor();
var alert = new AlertSystem();
alert.Subscribe(monitor);
monitor.SimulateTemperatureChange(25); // 无警报
monitor.SimulateTemperatureChange(32); // 触发警报
}
}
事件特点:
- 封装性:外部只能通过
+=
和-=
操作订阅/取消 - 安全性:防止外部直接调用或覆盖已注册的委托
- 标准模式:建议使用
EventHandler<TEventArgs>
作为基础委托
委托vs事件的关键区别
特性 | 委托 | 事件 |
---|---|---|
调用权限 | 外部可直接调用 | 只能在声明类内部触发 |
多播支持 | 支持 | 支持 |
空值检查 | 需要手动检查 | 由事件机制自动处理 |
封装性 | 低(公共委托字段有风险) | 高(只能通过事件访问) |
典型应用场景 | 回调机制、方法参数 | 观察者模式、通知系统 |
实际应用场景
- GUI 编程(如按钮点击事件)
- 异步操作完成通知
- 插件系统的事件通知
- 游戏开发中的玩家行为触发
- 物联网设备状态监控
最佳实践建议
- 总是使用
EventHandler<T>
作为事件基础类型 - 事件命名使用动词过去式(如
TemperatureChanged
) - 触发事件前检查是否为 null
- 使用
protected virtual
方法作为事件触发方法 - 在事件参数类名使用
EventArgs
后缀
通过理解委托和事件的关系,您可以更好地实现松耦合的代码结构。事件本质上是基于委托的封装,为观察者模式提供了更安全的实现方式。