Appearance
C# 委托与事件深度解析
委托和事件是 .NET 开发中极其重要的概念,也是理解很多高级特性(如 LINQ、异步编程、观察者模式)的基础。
1. 委托 (Delegate)
1.1 什么是委托?
委托是持有一个或多个方法引用的对象。它类似于 C++ 中的函数指针,但是它是类型安全且面向对象的。
委托定义了方法的“签名”(参数类型和返回类型)。
csharp
// 定义一个委托类型
public delegate void GreetingDelegate(string name);
// 使用委托
public static void EnglishGreeting(string name) => Console.WriteLine($"Hello, {name}");
public static void ChineseGreeting(string name) => Console.WriteLine($"你好, {name}");
static void Main()
{
GreetingDelegate del = EnglishGreeting;
del("Liker"); // 输出: Hello, Liker
}1.2 为什么使用委托?
- 将方法作为参数传递:使得程序具有更好的扩展性,避免大量的
if-else或switch逻辑。 - 解耦:调用方不需要知道具体执行的是哪个方法,只需要按照约定的签名调用即可。
1.3 多播委托 (Multicast Delegate)
一个委托变量可以绑定多个方法。使用 += 绑定方法,使用 -= 注销方法。
csharp
GreetingDelegate del = EnglishGreeting;
del += ChineseGreeting;
del("Liker"); // 依次调用 EnglishGreeting 和 ChineseGreeting2. 事件 (Event)
2.1 事件的由来
事件是对委托的封装。
- 如果直接使用
public delegate变量,外部可以直接赋值(覆盖掉已有的方法绑定),这破坏了封装性。 - 事件限制了外部只能使用
+=和-=,而不能直接赋值或在外部触发。
2.2 声明与使用
csharp
public class Heater
{
// 声明委托
public delegate void BoiledHandler(int temperature);
// 声明事件
public event BoiledHandler Boiled;
public void BoilWater()
{
// ... 烧水逻辑 ...
Boiled?.Invoke(95); // 只能在类的内部触发
}
}3. Observer (观察者) 设计模式
委托和事件是实现观察者模式的天然工具。
- Subject (监视对象):发布事件的类(如热水器)。
- Observer (监视者):订阅事件的类(如报警器、显示器)。
这种模式实现了对象间的松耦合:热水器不需要知道谁在监视它,它只负责在水开时发出信号。
4. .NET 框架中的规范
.NET 定义了一套标准的事件处理模式:
- 委托名称:以
EventHandler结尾。 - 委托签名:返回值为
void,接受两个参数:object sender(发布者) 和EventArgs e(事件数据)。 - 事件数据:继承自
EventArgs。
csharp
public class BoiledEventArgs : EventArgs
{
public int Temperature { get; }
public BoiledEventArgs(int temp) => Temperature = temp;
}
public delegate void BoiledEventHandler(object sender, BoiledEventArgs e);
public event BoiledEventHandler Boiled;5. 委托与异步调用
在 async/await 普及之前,委托的 BeginInvoke 和 EndInvoke 是实现异步编程的主要手段。
- BeginInvoke: 从线程池中抓取一个线程异步执行方法。
- EndInvoke: 获取异步方法的返回值,如果任务未完成则阻塞等待。
- AsyncCallback: 任务完成后的回调通知。
💡 提示:在现代 .NET 开发中,建议优先使用
Task和async/await代替委托的异步调用。
6. 总结
- 委托 是类型安全的方法指针。
- 事件 是委托的保护壳,提供了更好的封装性。
- 观察者模式 通过事件实现了组件间的松耦合。
- 异步委托 是历史悠久的并行编程方式,现在多被 Task 取代。
