CSharp-Learning/notes/10_Delegates_and_Events.md
Rosmontis_Cloud f604d53191 Initial commit: C# 学习笔记和示例代码
- Lesson 01-10: C# 基础语法
- WebView2: 集成示例
- notes/: 详细笔记
2026-07-01 16:31:35 +08:00

183 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 第十课:委托和事件
## 委托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<string> print = (msg) => Console.WriteLine(msg);
print("Hello"); // 无返回值
// Func: 有返回值的委托
Func<int, int, int> add = (a, b) => a + b;
int result = add(1, 2); // 3
// 多参数
Func<string, string, string> 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<string> 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 显示错误
```
事件让各部分解耦,不需要互相引用。