关于委托与事件触发

 Q: 模拟现实的一个问题:
比如说有一个公司(场景),你是老板,手下有主管和员工,作为老板你会指派(委托)主管管理员工的工作,如果某个员工玩游戏,则让某个主管从该员工的薪水里扣去500元钱。

这就是现实中的委托。

而在写程序中,假设程序员就是老板,有两个类分别为主管和员工,而主管小王和员工小张就是两个类的对象实例。员工类有一个方法:玩游戏,同时就有一个玩游戏的事件,他一玩游戏就会激发这个事件。而主管类就是负责处理该事件的,他负责把玩游戏的员工的薪水扣除500。

......

请高手们能帮我分析一下委托与事件触发吗?

谢谢了!~



A: 写这个程序的人真无聊,而且多多少少歪曲了“委托”的意思
身为程序员,还是应该用程序员的角度描述问题

“委托”,delegate,其实我觉得翻译成“代表”还好一点,它“代表”一个样子跟他差不多的方法。例如有以下方法:

private int DoSomething(string s) {...}

和以下委托(还是入乡随俗吧,我也叫委托好了):

public delegate int DoThingsDelegate(string s);

那么,因为样子差不多(术语叫“特征”(signature)相同——参数列表和返回值一样),这个委托就可以“代表”上面的方法。具体的“代表”的方法是:

private DoThingsDelegate varDoThingsDelegate; // 定义委托变量
varDoThingsDelegate = new DoThingsDelegate(DoSomething) // 将方法与委托连接起来
int returnValue = varDoThingsDelegate("hello!"); // 使用委托调用被代表的方法

以上三步缺一不可,但是第二步通常都不是我们自己做的——如果我们自己已经知道了方法名字,为什么不直接调用方法呢?我们通常都是1)定义委托,2)定义委托变量,3)让别人对委托变量赋值,4)把委托变量看成是个方法来调用。

这就推断出委托的使用场合:当我们要调用某个方法,但是我们只知道这个方法该长什么样子而不知道具体从哪里获得的时候,就是使用委托的时候。

.NET 里,有两个地方最常使用委托,首先就是事件,不过这个等下再说,然后就是异步调用方法。异步调用方法,简而言之,就是叫一个对象“开始”一项工作,但不需要立刻返回结果,我也不等待结果,继续我自己的工作,到这个对象“完成”,可以返回结果的时候再“告诉我”。整个故事的难点就是“告诉我”——这个对象怎么才能知道该怎么告诉我?为此,我在叫它“开始”工作的时候,顺便把我的一个方法包装成委托,告诉它“做完了之后,用这个方法告诉我”。这样,工作对象就不需要知道我是谁/什么,完成工作之后尽管调用委托就行了。

事件摆在异步之后说,是因为事件是一种特殊的委托——可以“代表”多个同特征方法的委托。考虑以下场景:雇员wang有一个PlayGame事件,雇员li交给wang一个委托,说“你玩游戏的时候告诉我”,然后雇员zhang也交给wang另一个委托:“你玩游戏的时候也告诉我”。那么,雇员wang必须找个方法将所有玩游戏委托都记住,以便通知所有人,以免三缺一。这种“多播委托”(MulticastDelegate)是事件的基本模型,在事件发生的时候由事件触发者通过调用委托来运行未知位置未知名字但已知特征的多个方法。

使用事件跟使用委托有一些区别。首先,符合委托特征的方法有了新名字:事件处理器(event handler),因为它的作用就是处理一个事件。然后,将委托交给事件所有者这个动作叫做“订阅”(subscribe),也就是说事件像周刊一样,发行的时候你就能收到一份。使用事件的步骤是

//1, 定义委托。该委托必须无返回(void),
//   因为事件如果存在多个订阅者,有返回值就乱套了。
//   委托类型的名字习惯用EventHandler或Handler结束,
//   因为这个委托类型代表的是事件处理器。
public delegate void PlayGameEventHandler(Employee starter, string gameName);
// public delegate void 委托类型名(参数列表);

//2,在对象里定义事件,即“委托变量”——多播委托变量
public event PlayGameEventHandler PlayGame;
// public event 委托类型名 事件名;

//3,由其他对象操作,订阅事件
wang.PlayGame += new PlayGameEventHandler(this.wang_PlayGame);
// 取消订阅只需要将上面的 += 改成 -=

// 这个是事件处理器的范例:
private void wang_PlayGame(Employee starter, string gameName)
{ Console.Write("我也要玩" + gameName + "!!"); }

//4,事件发生时,调用所有订阅者的事件处理器:
if (this.PlayGame != null) // 没有人订阅就会 == null
   this.PlayGame(this, "Tic Tac Toe");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值