.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("兄弟,没事,正常速度.");
                }
            }
        }
       
    }
}

 

 

 

 

 

 

 

posted @ 2013-05-12 16:56  --中庸--  阅读(268)  评论(0编辑  收藏  举报