首页 > 代码库 > 委托和事件

委托和事件

一、委托:是一个能够引用方法的对象。创建委托时实际是创建一个方法引用的对象,创建的引用对象能够调用方法。

  委托调用可以调用不同的方法,只需改变方法的引用即可。即委托调用方法是运行时确定,而非编译时确定。

  就像声名一个object实例一样,声名的只是一个占位符,具体指向哪个对象在运行时可以动态指定。在委托中指定方法有限制:返回值,参数类型要相同。

  

  委托声名:delegate ret-type delegatename(parameter-list)

  delegate 关键字声名委托

  ret-type是委托返回值类型

  delegatename 委托名称

  parameter-list 参数列表

  委托声名的是一个方法引用对象,被委托引用的方法返回值类型、形参类型必须与委托定义的相同,不限制是静态方法、还是实例方法。

  

  委托示例:  

技术分享
   //委托使用静态方法声名            StrMethodDelegate strdelegate = new StrMethodDelegate(StaticMethodClass.StaticStrMethod);            //调用方法            string result = strdelegate("HI");            Console.WriteLine(result);            //委托使用实例方法声名            InstanceClass instanceClass = new InstanceClass();            StrMethodDelegate instanceDelegate = new StrMethodDelegate(instanceClass.InstanceStrMethod);            result = instanceDelegate("Hi");
View Code

  运行结果:

  技术分享

   

 委托方法组转换:允许简单的为委托指定方法名称,不再使用new或者显示的调用构造函数。实际操作就像是变量赋值一样把方法赋值给方法引用。

  委托方法转换示例:  

技术分享
            VoidMethodDeleteage voidDelegateone = StaticMethodClass.FirstStaticEmpMethod;            voidDelegateone();            VoidMethodDeleteage voidDelegatetwo = new InstanceClass().FirstInstanceEmpMethod;            voidDelegatetwo();
View Code

   运行结果:

  技术分享

 

  委托多播:多播是指委托有创建方法调用列表,方法调用链表的能力。通过+、+=、-、-=运算符为链表添加方法。

  示例代码:  

技术分享
    VoidMethodDeleteage multi =             StaticMethodClass.FirstStaticEmpMethod;            multi += StaticMethodClass.SecondStaticEmpMethod;            InstanceClass incclass = new InstanceClass();            multi += incclass.FirstInstanceEmpMethod;            multi();            multi -= incclass.FirstInstanceEmpMethod;            multi();    
View Code

  运行结果:

  技术分享

  匿名方法赋值给委托

  使用delegate关键字创建匿名方法,可以赋值给委托。  

技术分享
VoidMethodDeleteage delte = delegate            {                for (int i = 0; i <= 5; i++)                {                    Console.Write(i);                    Console.Write(" ");                }            };            delte();
View Code

  运行结果:

  技术分享

 

  Lambda赋值给委托  

技术分享
 StrMethodDelegate delegateInc = n =>            {                return "Lambda ReturnValue:" + n;            };            string returnstr = delegateInc("Hello");            Console.WriteLine(returnstr);
View Code

  运行结果:

  技术分享

  使用匿名函数和lambad表达式和实例方法、静态方法一样能够进行方法的调用。 

  协变、逆变

  协变是指:只要方法的返回值类型派于委托声明的返回类型,该方法就可赋值给委托。

  逆变是指:只要方法参数的类型是委托声明类的父类,该方法即可赋值给委托。

 

  

二、事件:事件是基于委托类型,事件是一种信号机制,通知应用程序操作发生。

  工作原理是:如果对象对某事件感兴趣,则对象为事件注册事件的处理程序,事件发生时就会调用注册在事件上的处理程序。

  

  事件声明:使用Event关键字声明事件。

  Event event-delegate event-name

  Event声明事件关键字

  event-delegate 支持事件的委托声明,意思事件的注册程序通过委托来承载。

  event-name 具体的事件对象的名称。

  事件示例:  

技术分享
delegate void MyEventHandle(); static void Main(string[] args)        {            EventDemo demo = new EventDemo();            //注册事件            demo.SomeEvent += Handler;            //事件发生            demo.OnSomeEvent();            Console.ReadKey();        }        public static void Handler()        {            Console.WriteLine("Event ocurred");        }    class EventDemo    {        public event MyEventHandle SomeEvent;        //触发事件        public void OnSomeEvent()        {            if (SomeEvent != null)            {                SomeEvent();            }        }    }
View Code

  运行结果:

  技术分享

  

  事件多播

  事件是基于委托创建,所以事件是支持事件多播。

  事件多播示例  

技术分享
            EventDemo demo = new EventDemo();            //注册事件            demo.SomeEvent += Handler;            //事件多播,            demo.SomeEvent += MoreMethod.MoreMethodForEvent;            //事件发生            demo.OnSomeEvent();            Console.ReadKey();
View Code

  运行结果:

  技术分享

  

  事件存取器

  事件存取器类似属性存取器操作,通过存取器对事件控制更加灵活。

  事件可以使用匿名函数、和Lambda表达式,由于事件基本委托,所以事件的匿名函数、Lambda表达式同委托一样。

  

  .NET事件的指导原则

   为了使编写的组件与window兼容,开发人员需要遵循Microsoft建立的指导原则。事件处理程序必须有两个参数,

   第一个参数是产生事件的对象的引用,第二个参数为EventArgs类型。

   为了使事件遵循指导原则,再声明委托时使用delegate void MyEvent(object sender,EventArgs e),当然如果

    委托这么声明,那么委托调用的方法也要这样定义。

委托和事件