.NET 委托和事件

       什么叫委托

       委托就是只想一个函数的指针,使用委托可以让方法的引用封装在委托对象内,例如我是老板,需要以后我渴了的时候让小蜜给我打杯水,饿了就让他给我打水,门上安装个门铃,一按就让她给我打水和送吃的。这样我就可以将委托,将引用方法(打水)封装到委托对象(小蜜),以后我一按门铃,那么就是告诉我小我要喝水了,要吃东西了,小蜜就给我打水,至于门铃到底代表了什么,不管,我只是我说我又饿又渴,哈哈哈,我是不是太懒了。

      委托实现

     代码实现

         其实学习.net的大家应该都知道有这么一个东西,那么我们就先看一下,这个家伙怎么用。例如一个简短的例子:

<span style="font-size:14px;">class Program
    {
        //定义一个委托类型的saySomething,参数是name,返回值是void
        public delegate void saySomething(string name);

        static void Main(string[] args)
        {
            //调用委托方法
            saySomething ss = new saySomething(saySome.sayHelloToChinese);
            ss += new saySomething(saySome.sayHelloToEnglish);
            ss("孟海滨");
            ss("平晓微");
            ss.Invoke("孟海滨");
            Console.ReadLine();
        }
    }

    public class saySome
    {
        /// <summary>
        /// 一个静态方法,简单的打印一句话
        /// </summary>
        /// <param name="name">一个姓名的参数</param>
        public static void sayHelloToChinese(string name)
        {
            Console.WriteLine(name + ":你好");
        }

        /// <summary>
        /// 一个静态方法,简单的打印一句话
        /// </summary>
        /// <param name="name">一个姓名的参数</param>
        public static void sayHelloToEnglish(string name)
        {
            Console.WriteLine(name + ":hello");
        }
    }</span>
          看一下运行结果

      

          分析代码

       1.public delegate void saySomething(string name);   这里申明了一个Delegate的类型,名称为saySomething,返回值是void,参数是string

       2.为什么在最开始我说是一个函数的指针呢,大家看这行代码: ss += new saySomething(saySome.sayHelloToEnglish);他代表的就是指向saySome.sayHelloToEnglish这个函数。当然他和C++的函数指针还是有区别的,首先他可以搭载多个函数,而C++只能搭载一个,委托是安全的,面向对象的。

      3.Delegate在搭载多个方法时,可以通过+=增加搭载的函数,也可以通过-=来去掉Delegate中的某个函数。

      什么时候用

         加入有这么一个需求,汽车开车,当开到一定的距离的时候,报警器报警,就是是一次开到太多了,现在是汽车是一个实体,而报警器也是一个实体,如果用委托,他们可以这样实现。大家先看代码:

      汽车实体

<span style="font-size:14px;">public class Car
    {
       //定义委托类型,返回值是void,参数是int
       public delegate void Notify(int value);
       //定义一个事件
       public event Notify notifiers;

       //定义一个汽油的变量
       private int petorl;
       //汽油变量的set,get方法,在设置汽油数值的时候,判断汽油量是否充足
       public int Petorl
       {
           get { return petorl; }
           set {
               petorl = value;
               //如果汽油量少于10
               if (petorl < 10)
               {
                   //如果委托的对象不为空
                   if (notifiers != null)
                   {
                       //执行委托的放方法,委托的是什么?在这里不体现。
                       notifiers.Invoke(Petorl);
                   }
               }
           }
       }

       //构造函数,参数为汽油量(单位 :/L)
       public Car(int pertorl) {
           Petorl = pertorl;
       }

       //汽车启动的方法
       public void run(int speed) {
           //行走公里变量,单位(km/h)
           int distance = 0;

           //根据汽油量进行循环
           while (Petorl > 0)
           {
               //加上500ms跑speed公里
               Thread.Sleep(500);
               //汽油逐渐减少
               Petorl--;
               //行走公里数增加
               distance += speed;
               Console.WriteLine("汽车当前跑的公里数是" + distance.ToString());
           }
       }
    }</span>
       报警器
<span style="font-size:14px;">public class Alerter
    {
        //构造函数,将“显示汽油量不足的信息”的引用添加到汽车的委托中
        public Alerter(Car car)
        {
            //为car.notifiers 添加NotEnoughPetorl的引用
            car.notifiers += new Car.Notify(NotEnoughPetorl);
        }

        //显示汽油量不足的信息
        public void NotEnoughPetorl(int value)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("汽油量不足了" + value.ToString());
            Console.ResetColor();
        
        }
    }</span>

        客户端
<span style="font-size:14px;"> class Program
    {
        static void Main(string[] args)
        {
            //新建一个汽车,初始化的汽油量是15L
            Car car = new Car(15);
            //实例化报警器,将新建的气喘告诉他,让他添加一个油量不足的引用
            new Alerter(car);
            //奔跑吧汽车
            car.run(120);
        }
    }</span>

        看到上边的代码,有的朋友就会说了,我不用再汽车(Car)类里边用委托,直接实例化Alerter也可以呀,直接实例化,如果汽油量少于10,我就实例化一个报警器,然后去执行油量不足的提醒,也可以呀!

       是的,确实可以,但是看看如果我用了委托,我再汽车中有关于警报器的说法吗,是不是解耦合了,假如改天我的汽车改成烧气 的了,怎么办,我需要新加一个方法(提示天然气不足的),这个本来没什么,有了新的需求,增加代码本来就是应该的,但是我如果实例化报警器的话,那么我就需要修改汽车的类了,如果是委托呢,我执行要在报警器的类中做一定的扩充就可以,以前的代码完全不用改。这样看的话,是不是感觉委托更加牛了呢。

      Delegate和event

      大家可能看到上边有那么两句代码

       //定义委托类型,返回值是void,参数是int
       public delegate void Notify(int value);
       //定义一个事件
       public event Notify notifiers;
      这个事件是什么鬼,为什么我在第一个代码示例中就可以实现委托的功能,却要假一个事件,event与纯粹的delegate变量的最大区别就是增加了封装性。让delegate的触发权完全由对象控制,而delegate所委托的实际函数则由订阅者决定。event就是要执行一种“什么时候发生我说了算,发生的时候做什么事你说了算“的效果。而纯粹的delegate变量则在可访问的范围内同时给与指定委托函数与触发的权限。

      invoke和BeginInvoke的区别

     在第一个例子我用到了ss("孟海滨"),ss.invoke("孟海滨"),为什么要用invoke,他是个什么鬼invoke和BeginInvoke有详细的解释,大家可以看一下,这里我就不解释了。

     委托小结

       当我们在方法中需要函数指针等类似的东西的时候,当我们需要使用观察者模式的时候,当我们需要回掉函数的时候,可以考虑一下我们的委托,让我们降低类之间的耦合



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值