委托和事件

Posted 响马

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了委托和事件相关的知识,希望对你有一定的参考价值。

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

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

  就像声名一个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),当然如果

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

以上是关于委托和事件的主要内容,如果未能解决你的问题,请参考以下文章

原生js如何绑定a连接点击事件?

编写高质量代码改善C#程序的157个建议——建议137:委托和事件类型应添加上级后缀

jQuery事件绑定和委托实例

C#事件

概念篇-委托和事件

C#系列你应该知道的委托和事件