上一篇已经理解了委托的本质,我们就可以进入 C# 开发的"实战区"。
在现代 C# 开发中,我们很少再手动声明 delegate 关键字,而是直接使用微软提供的"全家桶":Action 和 Func。
1. 利用内置委托简化代码:Action 与 Func
这两个内置委托几乎覆盖了 99% 的应用场景,它们的区别非常简单:
Action:用于没有返回值 的方法(void)。Func:用于有返回值的方法。
简化对比
如果不使用内置委托,你需要先声明再使用;使用后,代码变得极其紧凑。
| 场景 | 传统自定义委托 | 使用 Action/Func (推荐) |
|---|---|---|
| 无返回值 | delegate void Log(string s); |
Action<string> |
| 有返回值 | delegate int Calc(int x, int y); |
Func<int, int, int> (最后一个是返回值类型) |
实例代码
csharp
// Action: 接收一个 string,返回 void
Action<string> logger = message => Console.WriteLine(message);
logger("Action 执行成功");
// Func: 接收两个 int,返回一个 int
// 语法:Func<参数1, 参数2, 返回值类型>
Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 10); // result = 15
2. 深入分析:委托在"事件(Event)"中如何工作
事件(Event)本质上是对委托的"封装"或"保护层"。
如果把委托比作一个"公开的呼叫名单",任何人都可以擦除或修改名单;那么事件就是"带锁的通知公告栏"------你只能订阅(+=)或取消订阅(-=),但不能清空整个名单(= null),也不能替主人发布消息。
事件的底层机制:发布-订阅模式
- 发布者(Publisher): 拥有委托,并决定何时触发它。
- 订阅者(Subscriber): 向委托注册自己的方法。
为什么需要 Event 而不是直接用 Delegate?
- 安全性: 在类外部,
event只能使用+=和-=。你不能在类外部直接调用myEvent(),也不能通过myEvent = null把别人的订阅给抹除。 - 职责分离: 事件确保只有拥有者才能触发通知。
3. 事件工作流程实例
让我们模拟一个"闹钟"场景:
csharp
using System;
// 1. 定义事件参数(习惯做法:继承 EventArgs)
public class AlarmEventArgs : EventArgs {
public string Message { get; set; }
}
public class AlarmClock {
// 2. 声明事件(使用内置的 EventHandler 委托类型)
// 这本质上是一个受保护的委托
public event EventHandler<AlarmEventArgs> AlarmTriggered;
public void StartAlarm() {
Console.WriteLine("闹钟正在倒计时...");
System.Threading.Thread.Sleep(1000);
// 3. 触发事件(发布通知)
// ?. 表示如果没有人订阅,就不执行
AlarmTriggered?.Invoke(this, new AlarmEventArgs { Message = "起床啦!" });
}
}
class Program {
static void Main() {
AlarmClock clock = new AlarmClock();
// 4. 订阅事件 (使用 +=)
clock.AlarmTriggered += (sender, e) => {
Console.WriteLine($"收到通知: {e.Message}");
};
clock.StartAlarm();
}
}
核心总结
- Action/Func 是委托的常用"模板",让我们省去了定义类型的麻烦。
- 委托 (Delegate) 是底层工具,提供了"方法指针"的能力。
- 事件 (Event) 是高级包装,它利用委托实现了安全的、受限的观察者模式。