### .NET委托的理解 在C#编程中,委托是一种引用类型的数据结构,它用来封装方法的引用。简单来说,委托可以被看作是函数指针的一种安全版本,它允许我们像传递变量一样传递方法。 #### 故事背景 在给定的代码故事中,我们讲述了一个有趣的场景,通过类比的形式帮助理解.NET中的委托概念。故事围绕着`Worker`(工人)和`Boss`(老板)两个角色展开,展示了如何通过委托来实现事件通知机制。 #### 基本概念 1. **委托定义**: - 在C#中,委托是一种数据类型,用于封装方法的引用。 - 定义委托时,我们需要指定该委托所引用的方法应该具有什么样的签名(即参数列表和返回类型)。 - 示例:`delegate void WorkStarted();` 定义了一个名为`WorkStarted`的无参数、无返回值的委托。 2. **委托实例化与调用**: - 创建委托实例后,可以通过该实例来调用实际绑定的方法。 - 使用`+=`运算符将方法绑定到委托实例上。 - 调用委托实例时,会执行所有绑定到该委托的方法。 3. **事件通知**: - 在C#中,事件是一种特殊的委托类型,通常用于对象间的通知机制。 - 事件提供了更安全的方式来管理多个方法的添加和移除。 - 示例:`public event WorkStarted onWorkStarted;` #### 代码示例分析 1. **初始版本**: - 初始版本中,`Worker`类通过`Advise`方法接收一个`Boss`类型的参数,并将其存储为私有成员变量。当`DoWork`方法被调用时,如果`_boss`不为空,则会依次调用`_boss`的`WorkStarted`、`WorkProgressing`和`WorkCompleted`方法。 - 这种方式直接依赖于`Boss`类型的具体实现,不够灵活。 2. **改进版本**: - 改进版本中,`Worker`类通过`Advise`方法接收一个实现了`IWorkerEvents`接口的对象,并将其存储为私有成员变量。这使得`Worker`类不再直接依赖于`Boss`类型,而是依赖于一个抽象接口。 - `IWorkerEvents`接口定义了三个方法:`WorkStarted`、`WorkProgressing`和`WorkCompleted`。这样,任何实现了这个接口的类都可以作为`Worker`的顾问,提高了系统的灵活性和可扩展性。 3. **最终版本**: - 最终版本中,采用了委托的方式进行事件通知。`Worker`类不再依赖于任何特定的类型或接口,而是通过三个委托(`WorkStarted`、`WorkProgressing`和`WorkCompleted`)来传递工作状态的变化。 - 当`DoWork`方法被调用时,如果相应的委托不为空,则会调用这些委托,进而触发绑定到委托上的方法。 #### 总结 通过这个C#睡前故事,我们可以清楚地看到.NET中委托的使用方式及其带来的灵活性和可扩展性。从最初直接依赖于具体类型的方法调用,到基于接口的解耦,再到利用委托进行事件通知,我们可以看到C#编程中处理事件通知的不同层次和方法。这种逐步递进的方式不仅加深了我们对委托的理解,也为我们在实际项目中选择合适的实现方案提供了参考。
class Worker {
public void Advise(Boss boss) { _boss = boss; }
public void DoWork() {
Console.WriteLine(“工作: 工作开始”);
if( _boss != null ) _boss.WorkStarted();
Console.WriteLine(“工作: 工作进行中”);
if( _boss != null ) _boss.WorkProgressing();
Console.WriteLine("“工作: 工作完成”");
if( _boss != null ) {
int grade = _boss.WorkCompleted();
Console.WriteLine(“工人的工作得分=” + grade);
}
}
private Boss _boss;
}
class Boss {
public void WorkStarted() { /* 老板不关心。 */ }
public void WorkProgressing() { /*老板不关心。 */ }
public int WorkCompleted() {
Console.WriteLine(“时间差不多!”);
return 2; /* 总分为10 */
}
}
class Universe {
Worker peter = new Worker();
Boss boss = new Boss();
peter.Advise(boss);
peter.DoWork();
Console.WriteLine(“Main: 工人工作完成”);
Console.ReadLine();
}
}
接口
现在,彼得成了一个特殊的人,他不但能容忍吝啬的老板,而且和他周围的宇宙也有了密切的联系,以至于他认为宇宙对他的工作进度也感兴趣。不幸的是,他必须也给宇宙添加一个特殊的回调函数Advise来实现同时向他老板和宇宙报告工作进度。彼得想要把潜在的通知的列表和这些通知的实现方法分离开来,于是他决定把方法分离为一个接口:
interface IWorkerEvents {
void WorkStarted();
void WorkProgressing();
int WorkCompleted();
}
class Worker {
public void Advise(IWorkerEvents events) { _events = events; }
public void DoWork() {
Console.WriteLine(“工作: 工作开始”);
if( _events != null ) _events.WorkStarted();
Console.WriteLine(“工作: 工作进行中”);
if(_events != null ) _events.WorkProgressing();
Console.WriteLine("“工作: 工作完成”");
if(_events != null ) {
剩余8页未读,继续阅读
- 粉丝: 0
- 资源: 2
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 自定义参照引用后保存显示主键或显示为空问题处理
- 我国1950-2023年外汇及黄金储备汇总+趋势变化图
- YOLOX,YOLOV5,YOLOV8,YOLOV9 针对 OpenVINO 的 C++ 推理,支持 float32、float16 和 int8 .zip
- 设置NCC单据参照字段多选(参照多选)
- 已安装xcb、X11库的交叉编译器(x86-64-aarch64-linux-gnu)
- 包含约100万条由BELLE项目生成的中文指令数据
- BIP集成NC65预算
- 包含约50万条由BELLE项目生成的中文指令数据
- 完整的交叉编译好支持xcb的qt库(qt5.15.2、arm64、xcb、no-opengl)
- 包含约40万条由BELLE项目生成的个性化角色对话数据,包含角色介绍