【转】C#事件、委托、回调的用法与区别

时间:2023-03-09 05:21:14
【转】C#事件、委托、回调的用法与区别

原文地址:http://blog.csdn.net/huang9012/article/details/38753305

事件包括:事件发送者、事件接收者和事件处理程序。
关于事件,我们首要知道的是事件的发送者必须知道发送什么类型的事件,以及相关
的事件参数。而事件的接收者必须了解其事件的处理方法必须使用的返回类型和参数

事件的发送者和事件的接收者都只关注事件而不是对方,这样对象就只需考虑自己,而不用
考虑其他对象。

例如:足球运动员踢球射门时,产生一个击球事件,但他并不用关心守门员是谁,他
只要关心自己踢球的角度、力度等事件参数,而守门员也一样,他只需关注如何接球即可。

足球运动员踢出球,产生一个击球事件,但是订阅该事件的可能并不只守门员,其他球员包括己
方和对方球员,甚至包括观众和裁判,他们都应该订阅该事件,因为球接下来会怎么样是未
知的,他们都应该做出相应的事件处理方法。

总之,一个事件总是由一个对象产生,但是一个事件可以由多个对象响应。

当多个对象订阅同一个事件时,IDE(Integrated Development Environment)就会把它们的事
件处理程序一个接一个地串起来关联到这个事件,并按照订阅顺序,先后执行。可以用+=增加事
件处理函数。

在上面中,我们一直讲事件触发时会调用对应的事件处理方法。但是,问题是他怎么知道调用
谁的事件处理方法。任何一个对象只要订阅了事件,他的是事件处理程序就会得到调用。然而
,事件对此该如何管理呢?

这就需要一个新的类型,叫做委托。
通过委托可以创建一个引用变量,但是并不是指向类的实例,而是指向一个类中的某个方法。

设计.NET事件的5步骤:
            1):定义参数类型:从类型EventArgs派生出满足要求的事件参数类
            2):定义事件处理者委托:与第一步相关该步一般被泛型委托取代了
            3):定义事件成员:在自定义类中,由事件处理者委托定义一个或多个事件成员
            4):触发事件:自定义类的引发事件方法中,通知所有事件订阅者
            5):订阅事件:注册事件处理程序
参数object sender 是产生这个事件对象的一个引用,例如处理一个按钮的单击事件,sender就
表示别单击的这个按钮。
如果没有事件数据,则传递 Empty,而不要传递 null。

可能你会执着于这样的一个问题:既然有了委托,那么事件干什么用的呢?
显然,委托可以干很多事情,但是他不知道什么时候干,这时候就需要事件来驱动。

或许你还会纠结于这样的一个问题:那为什么不直接让事件自己直接去做呢?
这就得回归到面向对象的思想上面了,面向对象讲究专注,就是一个对象最好只专注
自己的本职工作就可以,其他的事情就由其他相关的对象自己完成。

你想想,如果你是个老板,你可以触发一个事件(相当于你有某件事情),但如果处理这个事件
还要让你自己去做,你会觉得很麻烦,于是你就可以让你的职员(委托)去执行这些事件处理程序,
你只要在办公室里等待回复就可以了,这样是不是轻松了许多!

可能你没有当老板的命,无法体会,但换个例子,假如你想要买一张火车票,在没有委托之前,
毫无疑问,你得自己前晚火车站买票,但有了委托后,你就轻松了,你只要上网点击订票发布
一个事件,你的委托就会直接帮你买票,而你就不用大老远的自己跑去买票了。

生活中的例子其实很多,我们的父母其实一直充当着委托这个角色,在这里,感激他们一下:你
们辛苦了。

之前,我们说足球运动员踢球时会产生一个击球事件,并把这个击球事件与守门员直接联系
起来,这其实是不准确的,但我只是为了说明事件的作用而已。

准确的说,击球事件应该是足球运动员和球的,而球和守门员之间的事件应该是球飞出的事件。
现在我们要讨论的是这个击球事件:

既然如此,
那么假设,球场还有别的球,你可能无意中 帮这些球也订购了由运动员引发的击球事件,这样
子会造成一个后果,足球运动员一踢球这些所有的球都飞出去了。
后果严重把!

下面是关于回调的一些定义:(Callback Method)

回调:一个对象将一个方法的引用(方法的引用用委托保存)传入另一个对象,使得只有他能返
回信息,这就是一个回调。

回调方法是一种在操作或活动完成时由委托自动调用的方法。

回调不同于事件,回调不能发布,不是类型,是一种设计模式,回调在两个类之间建立一种关系,
其中一个对象会自动对另一个对象做出反应,回调一般是私有的,保存回调的类对于谁能访问这个
回调有所控制,回调通常在对象的构造函数中设置。

本人粗略定义:简单的说就是将委托作为参数传递给某个特定对象。

这样,有了回调我们就可以避免上面非赛场上的球也飞出去的问题了。