理解委托(转载)
来源:互联网 发布:上市公司财务报表数据 编辑:程序博客网 时间:2024/05/16 04:44
事件与委托似乎很难以理解,这是因为它们的使用方式与常用的编码有很大的差别,例如通常编写的都是同步代码,调用一个类型的方法,会即刻出现方法执行的结果,这是符合逻辑的。但在某些情况中,同步代码未必满足需求,拿公共汽车来打个比方,如果交通管制中心希望每一辆公车到达一个站点时都发送给自己一个信号以便自己能够随时掌握交通状况,使用同步代码,公汽对象肯定需要调用管制中心对象,这样就出现了我们一直不愿意看到的情况:两个类型紧密地耦合在一起。既然要其它类型对自己的行为作出反应,亲自调用其类型的方法似乎不可避免,在同步代码中,很难避免这种紧密的类型调用关系。
另一个差别是在一般情况下,我们只将属性作为参数传递给方法,而很少会考虑将一个方法传递给另一个方法。
我们抛弃各种C#参考书中桀骜难懂的事件与委托概念,设想一个情景来理解事件与委托的使用:有一家IT公司,董事长不希望自己的雇员在上班时间玩游戏,但又不可能每时每刻都盯着每个雇员,因此,他希望使用一种新的方式实现监视雇员的效果:如果有雇员违反规定,某个设备或专门的监查人员将自动发出一个消息通知他,董事长只需要在事情发生时进行处理。
因此,这个用例实际上是两种类型——董事长类与雇员类——之间的交互,下面的代码将给读者展示如何使用委托与事件机制实现这种交互:
首先,我们需要在董事长类与雇员类之间定义一个委托类型,用于传递两者之间的事件,这个类型就是一个监视设备或专门负责打小报告的监查人员:
public delegate void DelegateClassHandle();
定义一个委托的过程类似方法的定义,但它没有方法体。定义委托一定要添加关键字delegate。由于定义委托实际上相当一个类,因此可以在定义类的任何地方定义委托。另外,根据委托的可见性,也可以添加一般的访问修饰符,如public、private和protected。
委托的返回值类型为void,这并非表示委托类型本身带有返回值,该返回值类型是指委托的目标函数类型,即它委托的一个事件处理函数返回值是void类型。
新建一个雇员类Employee,其代码如下:
public class Employee{ public event DelegateClassHandle PlayGame; public void Games() { if (PlayGame != null) { PlayGame(); } }}
public class Admin{ public void Notify() { System.Console.WriteLine("someone is playing game"); }}
Employee employee = new Employee();Admin admin = new Admin(); employee.PlayGame += new DelegateClassHandle(admin.Notify);
employee.PlayGame += new DelegateClassHandle(admin.Notify);
public class CustomeEvetnArgs : EventArgs{ string name = ""; int age = 0; public CustomeEvetnArgs() { } public string Name { get { return this.name; } set { this.name = value; } } public int Age { get { return this.age; } set { this.age = value; } }}
public delegate void DelegateClassHandle(object sender, CustomeEvetnArgs e);
public class Employee{ private string _name; public string Name { get { return _name; } set { _name = value; } } private int _age; public int Age { get { return _age; } set { _age = value; } } public event DelegateClassHandle PlayGame; public void Games() { if (PlayGame != null) { CustomeEvetnArgs e = new CustomeEvetnArgs(); e.Name = this._name ; e.Age = this._age; PlayGame(this, e); } }}
public class Admin{ public void Notify(object sender, CustomeEvetnArgs e) { System.Console.WriteLine(e.Name+" is "+e.Age.ToString()); }}
Employee employee = new Employee();employee.Name = "Mike";employee.Age = 25;Admin admin = new Admin(); employee.PlayGame += new DelegateClassHandle(admin.Notify);employee.Games();
public class Manager{ public void Notify(object sender, CustomeEvetnArgs e) { System.Console.WriteLine(sender.ToString() + "-" + e.Name); }}
Employee employee = new Employee();employee.Name = "Mike";employee.Age = 25;Admin admin = new Admin();Manager manager = new Manager(); employee.PlayGame += new DelegateClassHandle(admin.Notify);employee.PlayGame += new DelegateClassHandle(manager.Notify);employee.Games();
执行该方法,读者将看到admin和manager的Notify方法都会被事件通知并调用执行。通过这样的方法,董事长和经理都会知道Mike在玩游戏了。
如果董事长不希望经理也收到这个通知,该如何解除PlayGame对manager的事件绑定呢?同样非常简单,在employee.Games方法被调用前执行下列语句即可:
employee.PlayGame -= new DelegateClassHandle(manager.Notify);
最后需要提醒读者注意的,Employee类中的Games方法在触发事件PlayGame之前需要判断该事件是否为null。当employee对象的Games方法触发事件PlayGame后,必须有一个目标函数来处理这个事件,而该语句正是判断该目标函数是否存在。如果将这个判断去掉,且对事件不进行任何绑定而直接调用Games方法,程序将在事件PlayGame处弹出一个NullReferenceException的异常。
读者能够从委托与事件的代码中得出什么结论吗?两个需要存在调用关系的类型,在各自的实现中却没有编写实际的调用代码,它们只是通过一个事件和一个第三方的委托类型完成了消息的传递过程。两个类型之间不存在任何的紧密耦合,它们看似松散地通过一个委托对象中通信,实现了本书一直宣传的“高聚合”和“低耦合”观点。
来自:http://blog.csdn.net/chiangbt/archive/2008/01/17/2050174.aspx
- 理解委托(转载)
- C#委托-概念理解(转载)
- C#委托,事件理解入门 转载
- C# 委托 介绍(转载)
- 转载: 深入理解iPhone委托模式兼谈iPhone生命周期
- 代理(委托)的理解
- 什么是委托,理解委托
- 什么是委托,理解委托
- 理解委托
- 委托理解
- 理解委托
- .net的事件与委托(转载)
- C#委托和事件分析(转载)
- C# 事件与委托(转载)
- container_of 理解(转载)
- hibernate理解(转载)
- C#中委托,事件理解(摘)
- 理解委托(国王的故事)
- 浅谈大学教育制度
- glLoadIdentity
- 剖析Qt Creator布局管理器
- socket
- android系统中的log定向
- 理解委托(转载)
- JSON异步处理数据
- 稻香村
- Gearman的使用
- 我在提高班
- C#& ASP.NET学习笔录1(C#集合小例)
- PCI总线系统体系结构
- VC对话框设置背景位图三种方法
- JAVA 数据库测试框架DBUnit之Hibernate篇