zoukankan      html  css  js  c++  java
  • .net委托与事件 中庸

        很久没有写文章了,最近看了点书,有点小感悟,写出来,以纪念曾逝去的青春,纯属自娱,写的有不对的地方,望各位同仁批评

     指正。

    目录:

        1.普通调用与回调

        2.用委托实现回调

        3.委托与事件

     进入正题。

     一,普通调用与回调

             普通调用,也是我们最常用的调用,往往是高层代码(应用程序)调用低层的函数(如系统函数,库函数等) 。

             回调(callback),指的是可以作为参数传给其他代码的一段可执行代码.回调时,则是在低层函数执行时调用高层的代码。

            如果高层和低层分别是一个实体的话,那么普通调用实现的是上调用下,回调实现的是下调用上,这样就实现了高层与低层之间的

           双向通信。

            回调举例:

                  如果我们用js异步调用webservice的话,经常会传递两个函数,分别是执行成功和失败时执行的函数,实际上这两个函数

            就是webservice的回调函数。当我们将函数传递过去后,webservice将调用的方法执行完后,报告我们的成功和失败函数.即

            我们调用Webservice的方法,webservice触发间接调用我们的方法,实现双向调用。

     二,用委托实现回调

                历史上,Windows API经常使用C语言风格的函数指针来创建回调函数,使用回调,程序员可以使一个函数返回报告(即回调)

          给程序中的另一个函数.不过,C语言风格回调函数的缺点在于,它们除了原始内存地址外无法表示其他信息,理想中的回调应该包

         含更多类型安全信息,例如参数的数量与类型,所指向方法的返回值(有的话)。尽管如此,回调仍然很有用。

              .net中的回调就是使用更为安全和面向对象的委托来完成的。本质上来讲,委托是一个类型安全的对象,它指向程序中另一个以

         后会被调用的方法。

          回调实例:       

    用委托实现回调代码
    namespace DelegateTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Car car = new Car("跑车", 100, 40);
    
                car.RegisterCarEngine(OnCarEngineHandler);
    
                car.Accelerate(70);
    
    
                Console.Read();
            }
    
            static void OnCarEngineHandler(int maxsd, int currsd)
            {
                if (currsd >= maxsd)
                {
                    Console.WriteLine(String.Format("已经超速,当前速度为:{0}",currsd));
                }
                else if (currsd > maxsd - 10)
                {
                    Console.WriteLine(String.Format("离最大速度已经小于10,当前速度已经到:{0}",currsd));
                }
                else
                {
                    Console.WriteLine("哥们,没事,正常速度.");
                }
            }
        }
    
        class Car
        {
            public int CurrentSpeed { get; set; }
    
            public int MaxSpeed { get; set; }
    
            public string PetName { get; set; }
    
    
            public Car(string name,int maxSp,int currSp)
            {
                PetName = name;
                MaxSpeed = maxSp;
                CurrentSpeed = currSp;
            }
    
            public delegate void CarEngineHandler(int maxSpd,int currSpd);
    
            private CarEngineHandler carEngineHandler;
    
    
            public void RegisterCarEngine(CarEngineHandler carenginehandler)
            {
                carEngineHandler += carenginehandler;
            }
    
    
            public void Accelerate(int delta)
            {
                if (carEngineHandler != null)
                {
                    carEngineHandler.Invoke(MaxSpeed, CurrentSpeed+delta);
                }
            }
        }
    }

      三,委托与事件

              本质上,事件只是委托的封装,就像一个语法糖一样
              委托变量必须定为私有,否则为引发两个问题:

                      1.调用者可以把委托变量重新赋值,这样就删除了当前要调用的方法列表

                      2.调用者可以直接调用委托变量的方法列表
            既然委托变量必须定位私有的,就要为委托变量创建自定义的注册和注销方法来保护封装等 而如果定义该委托的事件变量,就可

           以省去这些代码量.定义事件变量之后,有相应缺点的两个好处:

                     1.事件的操作符只有两个+=和-=,这样就不会引发覆盖方法列表的情况

                     2.调用者不可直接调用事件的方法列表

           事件实例:

    事件实例
    namespace EventTest
    {
        class Program
        {
            static void Main(string[] args)
            {
                Car car = new Car("跑车", 100, 20);
                car.Exploded += OnAboutToBlowHandler;
                car.AboutToBlow += OnAboutToBlowHandler;
                car.Accelerate(100);
    
    
                Console.Read();
            }
    
            static void OnExplodedHandler(Car car,CarEventArgs e)
            {
                if (car != null)
                {
                    Console.WriteLine(String.Format("{0},要被罚款了啊,当前已超过最高速度:{1}公里",e.msg,car.CurrentSpeed-car.MaxSpeed));
                }
            }
    
            static void OnAboutToBlowHandler(Car car, CarEventArgs e)
            {
                if (car != null)
                {
                    Console.WriteLine(String.Format("{0},小心,当前速度,离最高速度还有:{1}公里", e.msg, car.MaxSpeed - car.CurrentSpeed));
                }
            }
        }
    
        public class CarEventArgs : EventArgs
        {
            public readonly string msg;
    
            public CarEventArgs(string message)
            {
                msg = message;
            }
        }
    
        public class Car
        {
            public delegate void CarEngineHandle<T>(T eventSourceObject ,CarEventArgs args);
    
            public event CarEngineHandle<Car> Exploded;
    
            public event CarEngineHandle<Car> AboutToBlow;
    
            public int MaxSpeed { get; set; }
    
            public int CurrentSpeed { get; set; }
    
            public String PetName { get; set; }
    
            public Car(String name, int maxSd, int currSd)
            {
                PetName = name;
                MaxSpeed = maxSd;
                CurrentSpeed = currSd;
            }
    
            public void Accelerate(int delta)
            {
                if (CurrentSpeed + delta > MaxSpeed)
                {
                    if (Exploded != null)
                    {
                        Exploded(this,new CarEventArgs("老兄,严重超速了啊"));
                    }
                }
                else
                {
                    CurrentSpeed += delta;
                    if (CurrentSpeed + 10 > MaxSpeed)
                    {
                        if (AboutToBlow != null)
                        {
                            AboutToBlow(this,new CarEventArgs("老兄,快超速了啊"));
                        }
                    }
                    else
                    {
                        Console.WriteLine("兄弟,没事,正常速度.");
                    }
                }
            }
           
        }
    }
  • 相关阅读:
    TCC
    使用RocketMQ实现分布式事务
    CentOS关机
    使用grub手动引导linux和windows
    CentOS下X Window与命令行界面的切换
    Centos下 为firefox安装flash插件
    tar.xz文件如何解压
    用Linux命令wget进行整站下载
    CentOS关闭火狐浏览器Flash过期提示
    CentOS普通用户添加sudo权限
  • 原文地址:https://www.cnblogs.com/liangjie/p/3074281.html
Copyright © 2011-2022 走看看