首页 > 代码库 > 事件的前世今生,委托和事件关系

事件的前世今生,委托和事件关系

    假设没有事件,我们能不能通过委托实现事件的功能?事实上是可以的。下面我们一步一步剖析!先举个例子:

    有这么一个场景,有一个气球(相当于事件、消息的发送者),气球爆炸(相当于触发事件),小孩子听到气球爆炸会吓哭(小孩子相当于一个事件的订阅者)。我们不适用事件,使用委托来完成这个程序。

   第一步:定义一个全局的委托类型, 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();//调用委托            

             }                    

      }    

}