差别
这里会显示出您选择的修订版和当前版本之间的差别。
| 两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
| csharp:系统关键字 [2025/11/28 11:09] – [关键词速查表] 张叶安 | csharp:系统关键字 [2025/11/28 11:12] (当前版本) – [5. Event (事件) 关键词] 张叶安 | ||
|---|---|---|---|
| 行 136: | 行 136: | ||
| double area = Tools.Pi * 10 * 10; // 不需要 new Tools() | double area = Tools.Pi * 10 * 10; // 不需要 new Tools() | ||
| </ | </ | ||
| + | |||
| + | |||
| + | ==== 5. Event (事件) 关键词 ==== | ||
| + | |||
| + | 在 C# 中,**event** 关键词用于在类或对象中声明事件。事件允许类或对象在发生某些特定情况时通知其他类或对象。这是一种基于 **发布-订阅 (Publish-Subscribe)** 模式的机制。 | ||
| + | |||
| + | === 1. 核心概念 === | ||
| + | |||
| + | * **发布者 (Publisher)**:定义事件并决定何时触发事件的类。 | ||
| + | * **订阅者 (Subscriber)**:监听事件并在事件触发时执行特定操作的类。 | ||
| + | * **委托 (Delegate)**:事件底层的类型安全函数指针,定义了事件处理程序的签名。 | ||
| + | |||
| + | === 2. 语法结构 === | ||
| + | |||
| + | 声明一个事件通常包含两个步骤: | ||
| + | - 1. 定义委托(或者使用系统内置的 `EventHandler`)。 | ||
| + | - 2. 使用 `event` 关键词声明事件变量。 | ||
| + | |||
| + | <code csharp> | ||
| + | public delegate void MyEventHandler(string message); // 1. 定义委托 | ||
| + | public event MyEventHandler OnProcessCompleted; | ||
| + | </ | ||
| + | |||
| + | === 3. 实战案例 === | ||
| + | |||
| + | 以下是一个完整的控制台程序案例,模拟了一个视频编码器(发布者)和邮件服务(订阅者)。 | ||
| + | |||
| + | == 案例代码 == | ||
| + | |||
| + | <code csharp> | ||
| + | using System; | ||
| + | |||
| + | namespace EventDemo | ||
| + | { | ||
| + | // 1. 定义包含事件数据的类 (可选,但推荐) | ||
| + | public class VideoEventArgs : EventArgs | ||
| + | { | ||
| + | public string Title { get; set; } | ||
| + | } | ||
| + | |||
| + | // 2. 发布者:视频编码器 | ||
| + | public class VideoEncoder | ||
| + | { | ||
| + | // 声明事件:使用内置的 EventHandler< | ||
| + | // 这里的 event 关键词是核心 | ||
| + | public event EventHandler< | ||
| + | |||
| + | public void Encode(string title) | ||
| + | { | ||
| + | Console.WriteLine($" | ||
| + | System.Threading.Thread.Sleep(1000); | ||
| + | |||
| + | // 触发事件 | ||
| + | OnVideoEncoded(title); | ||
| + | } | ||
| + | |||
| + | // 按照约定,创建一个受保护的虚方法来触发事件 | ||
| + | protected virtual void OnVideoEncoded(string title) | ||
| + | { | ||
| + | // 检查是否有订阅者 (VideoEncoded != null) | ||
| + | VideoEncoded? | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // 3. 订阅者:邮件服务 | ||
| + | public class MailService | ||
| + | { | ||
| + | // 事件处理程序:签名必须与委托匹配 | ||
| + | public void OnVideoEncoded(object source, VideoEventArgs e) | ||
| + | { | ||
| + | Console.WriteLine($" | ||
| + | } | ||
| + | } | ||
| + | |||
| + | // 4. 主程序 | ||
| + | class Program | ||
| + | { | ||
| + | static void Main(string[] args) | ||
| + | { | ||
| + | var video = new VideoEncoder(); | ||
| + | var mailService = new MailService(); | ||
| + | |||
| + | // 订阅事件:使用 += 操作符 | ||
| + | video.VideoEncoded += mailService.OnVideoEncoded; | ||
| + | |||
| + | video.Encode(" | ||
| + | } | ||
| + | } | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | == 输出结果 == | ||
| + | |||
| + | <code text> | ||
| + | 正在编码视频: | ||
| + | 邮件服务:发送邮件,视频 ' | ||
| + | </ | ||
| + | |||
| + | === 4. 关键点总结 === | ||
| + | |||
| + | * **封装性**:`event` 关键词为委托实例提供了一层封装。在类的外部,客户端只能使用 `+=` (订阅) 和 `-=` (取消订阅),而不能直接使用 `=` 赋值(这会覆盖其他订阅者)或直接调用 `Invoke()`。 | ||
| + | * **空检查**:在触发事件前,务必检查事件是否为 `null`(即是否有订阅者),C# | ||
| + | * **命名规范**:事件通常命名为 `Name` 或 `OnName`,处理方法通常命名为 `OnName`。 | ||