首页 > 代码库 > 事件的前世今生,委托和事件关系
事件的前世今生,委托和事件关系
假设没有事件,我们能不能通过委托实现事件的功能?事实上是可以的。下面我们一步一步剖析!先举个例子:
有这么一个场景,有一个气球(相当于事件、消息的发送者),气球爆炸(相当于触发事件),小孩子听到气球爆炸会吓哭(小孩子相当于一个事件的订阅者)。我们不适用事件,使用委托来完成这个程序。
第一步:定义一个全局的委托类型, public delegate void BombEventHandler();//定义了一个委托,其实是一个类吧,相当于一个委托类
第二步:定义气球类(BalloonPublisher),很简单,这个类仅仅用友一个爆炸的方法,爆炸就发出消息,我爆炸了,也就是调用bomb委托
public class BalloonPublisher
{ public BombEventHandler Bomb;//委托类型的变量
public void BalloonBomb()
{
if (Bomb != null)
{
Bomb();//调用委托
}
}
}
第三步:我们实现订阅者,小孩子类,为了简单我们仅仅定义一个被吓哭的方法
public class ChildrenSubscribe
{
//其实订阅委托
public void OnHearBomb()
{
Console.WriteLine("我被爆炸伤吓哭了");
}
}
一切定义好了,就等着关联了,客户端进行关联:
static void Main(string[] args)
{
//客户端触发事件,并订阅事件
BalloonPublisher pb = new BalloonPublisher();
ChildrenSubscribe sb = new ChildrenSubscribe();
pb.Bomb += sb.OnHearBomb; //是不是很熟悉?关键气球爆炸委托和小孩子听到爆炸后的方法
pb.BalloonBomb();//触发爆炸事件,其实是执行委托
}
执行结果很明白,当爆炸触发时候,小孩子吓哭这个方法也在这个委托链上所以也就执行了吓哭方法。
回顾下上面的过程,和事件功能完全一样,说明委托完全可以实现事件的功能!可是为什么会有事件的产生呢?对上面的例子我们可以这么想,气球爆炸是属于气球本身的,与客户端没关系,只有气球才能触发爆炸这个方法,可是我们上面这个例子是可以通过客户端直接触发气球爆炸的,比如 pb.Bomb();直接触发爆炸委托,也能把小孩吓哭。这样就破坏了封装性。这是事件产生的第一个原因。
假如气球爆炸后,不仅仅引起小孩子哭,还会引起大人寻找那的气球爆炸了,周围的鸟也会飞走等一系列事件。这就需要把这些方法都得加入到委托连pb.Bomb中去。
如果客户端不小心把把这个委托连弄断了或者改变了,将会引起很大的麻烦,所有订阅的类都失败了。
为了解决以上问题,事件才应运而生的,其实事件就是对委托的封装罢了,具体内部实现我就不多说了,网上多的是。
下面给出利用事件完成此功能的程序:其实很简单,把气球类里面的委托换成事件定义即可,这样以后,你在客户端 直接调用pb.BombEvent();是有语法错误的,从而确保了封装性和事件也只能有气球本身触发,与客户端没任何关系
public class BalloonPublisher
{
public event BombEventHandler BombEvent; //我加了Event的后缀
public void BalloonBomb()
{
if (BombEvent != null)
{
BombEvent();//调用委托
}
}
}