# 第十课:委托和事件 ## 委托(Delegate)是什么 委托 = 函数的"容器",可以把函数当作变量传递。 ```csharp // 声明委托类型 delegate int Calculator(int a, int b); // 定义符合委托的方法 int Add(int a, int b) => a + b; int Multiply(int a, int b) => a * b; // 使用委托 Calculator calc = Add; int result = calc(1, 2); // result = 3 calc = Multiply; result = calc(3, 4); // result = 12 ``` ## 为什么需要委托 ```csharp // 场景:数组遍历时对每个元素做操作 void ProcessNumbers(int[] numbers, ??? operation) { foreach (int n in numbers) { ??? result = operation(n); Console.WriteLine(result); } } // 没有委托,你需要写多个重载 // 有委托,可以传任意操作 ProcessNumbers(nums, x => x * 2); // 翻倍 ProcessNumbers(nums, x => x + 1); // +1 ProcessNumbers(nums, x => x * x); // 平方 ``` ## Action 和 Func(简化委托) ```csharp // Action: 返回 void 的委托 Action print = (msg) => Console.WriteLine(msg); print("Hello"); // 无返回值 // Func: 有返回值的委托 Func add = (a, b) => a + b; int result = add(1, 2); // 3 // 多参数 Func concat = (a, b) => a + b; string s = concat("Hello", " World"); // "Hello World" ``` ## 事件(Event)是什么 事件 = 委托的升级版,只能 += 添加监听,不能外部直接调用。 ```csharp class Button { // 事件声明 public event Action Clicked; public void OnClick() { Console.WriteLine("按钮被点击"); // 触发事件(只能在类内部) Clicked?.Invoke(); } } ``` ```csharp // 使用事件 Button btn = new Button(); // 添加监听者 btn.Clicked += () => Console.WriteLine("Handler 1 执行"); btn.Clicked += () => Console.WriteLine("Handler 2 执行"); btn.OnClick(); // 输出: // 按钮被点击 // Handler 1 执行 // Handler 2 执行 ``` ## 事件 + 委托的应用场景 ```csharp class Microphone { // 事件声明 public event Action OnTranscriptReady; // 识别出文字时触发 public event Action OnListeningStarted; public event Action OnListeningStopped; private bool isListening; public void StartListening() { isListening = true; Console.WriteLine("麦克风开始监听..."); OnListeningStarted?.Invoke(); } public void StopListening() { isListening = false; Console.WriteLine("麦克风停止监听..."); OnListeningStopped?.Invoke(); } // 模拟识别到文字 public void TranscriptDetected(string text) { Console.WriteLine($"识别到: {text}"); OnTranscriptReady?.Invoke(text); // 触发事件,通知所有监听者 } } ``` ```csharp // 使用 Microphone mic = new Microphone(); // 订阅事件 mic.OnTranscriptReady += (text) => { Console.WriteLine($"收到文字: {text}"); }; mic.OnListeningStarted += () => { Console.WriteLine("开始记录..."); }; mic.OnListeningStopped += () => { Console.WriteLine("停止记录"); }; // 触发 mic.StartListening(); mic.TranscriptDetected("今天天气不错"); mic.TranscriptDetected("大家一起加油"); mic.StopListening(); ``` ## 事件 vs 委托 | | 委托 | 事件 | |---|---|---| | 外部添加监听 | ✓ | ✓ | | 外部调用 | ✓ | ✗ | | 主要用途 | 传递函数 | 通知机制 | ## 移除监听 ```csharp Action handler = () => Console.WriteLine("Handler"); btn.Clicked += handler; btn.Clicked -= handler; // 移除 ``` ## 实际项目结构 ``` 语音识别服务 ├── OnTranscriptReady(text) → UI 更新文字 ├── OnListeningStarted() → UI 显示监听状态 ├── OnListeningStopped() → UI 停止动画 └── OnError(error) → UI 显示错误 ``` 事件让各部分解耦,不需要互相引用。