上一篇已經(jīng)理解了委托的本質(zhì),我們就可以進入 C# 開發(fā)的“實戰(zhàn)區(qū)”。
在現(xiàn)代 C# 開發(fā)中,我們很少再手動聲明 delegate 關鍵字,而是直接使用微軟提供的“全家桶”:Action 和 Func。
1. 利用內(nèi)置委托簡化代碼:Action 與 Func
這兩個內(nèi)置委托幾乎覆蓋了 99% 的應用場景,它們的區(qū)別非常簡單:
-
Action:用于沒有返回值的方法(void)。 -
Func:用于有返回值的方法。
簡化對比
如果不使用內(nèi)置委托,你需要先聲明再使用;使用后,代碼變得極其緊湊。
| 場景 | 傳統(tǒng)自定義委托 | 使用 Action/Func (推薦) |
|---|---|---|
| 無返回值 | delegate void Log(string s); |
Action<string> |
| 有返回值 | delegate int Calc(int x, int y); |
Func<int, int, int> (最后一個是返回值類型) |
實例代碼
// Action: 接收一個 string,返回 void
Action<string> logger = message => Console.WriteLine(message);
logger("Action 執(zhí)行成功");
// Func: 接收兩個 int,返回一個 int
// 語法:Func<參數(shù)1, 參數(shù)2, 返回值類型>
Func<int, int, int> add = (a, b) => a + b;
int result = add(5, 10); // result = 15
2. 深入分析:委托在“事件(Event)”中如何工作
事件(Event)本質(zhì)上是對委托的“封裝”或“保護層”。
如果把委托比作一個“公開的呼叫名單”,任何人都可以擦除或修改名單;那么事件就是“帶鎖的通知公告欄”——你只能訂閱(+=)或取消訂閱(-=),但不能清空整個名單(= null),也不能替主人發(fā)布消息。
事件的底層機制:發(fā)布-訂閱模式
- 發(fā)布者(Publisher): 擁有委托,并決定何時觸發(fā)它。
- 訂閱者(Subscriber): 向委托注冊自己的方法。
為什么需要 Event 而不是直接用 Delegate?
-
安全性: 在類外部,
event只能使用+=和-=。你不能在類外部直接調(diào)用myEvent(),也不能通過myEvent = null把別人的訂閱給抹除。 - 職責分離: 事件確保只有擁有者才能觸發(fā)通知。
3. 事件工作流程實例
讓我們模擬一個“鬧鐘”場景:
using System;
// 1. 定義事件參數(shù)(習慣做法:繼承 EventArgs)
public class AlarmEventArgs : EventArgs {
public string Message { get; set; }
}
public class AlarmClock {
// 2. 聲明事件(使用內(nèi)置的 EventHandler 委托類型)
// 這本質(zhì)上是一個受保護的委托
public event EventHandler<AlarmEventArgs> AlarmTriggered;
public void StartAlarm() {
Console.WriteLine("鬧鐘正在倒計時...");
System.Threading.Thread.Sleep(1000);
// 3. 觸發(fā)事件(發(fā)布通知)
// ?. 表示如果沒有人訂閱,就不執(zhí)行
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();
}
}
核心總結(jié)
- Action/Func 是委托的常用“模板”,讓我們省去了定義類型的麻煩。
- 委托 (Delegate) 是底層工具,提供了“方法指針”的能力。
- 事件 (Event) 是高級包裝,它利用委托實現(xiàn)了安全的、受限的觀察者模式。