zoukankan      html  css  js  c++  java
  • 委托和事件

    委托

    1.什么是委托?

    委托是安全的函数指针,所谓的安全是指它的参数的类型是确定的,它的参数的个数是固定的。委托是一种数据类型,它和类是同级的,委托的是对方法的一种抽象,使用委托可以将方法作为参数进行传递。

    2.委托的使用步骤

    (1)定义委托类型,一般约定 “名称+delegate”来命名委托

     public delegate void GreetDelegate(string msg);

    (2)使用委托定义委托变量

    GreetDelegate  greetDelegate;

    (3)为委托变量赋值

    greetDelegate =new GreetDelegate(ChineseSayHello)

    或者

    greetDelegate=ChineseSayHello;(这一步也就是相当于事件中的订阅事件)

    public void ChineseSayHello(string msg)

    {

          Console.WriteLine(msg);

    }

    (4).调用委托

    greetDelegate("世界你好");//相当于事件中的发布事件

    greetDelegate.Invoke(“世界你好2”);

    3.委托的应用

    (1)在前面也已经稍微的描述过了,就是构成了一种调用机制——发布订阅机制,一方可以通过委托监视另一方,当一方被调用的时候绑定的委托的方法也随之调用,这种应用已经完全的被事件所代替,事件更加的安全在实现的过程中,因为事件是不允许使用“=”,这样就可以避免将已经订阅的方法掩盖。

    (2)另一种重要的应用,也是委托的核心,就是可以将函数作为参数进行传递,所以说委托是对方法的一种抽象啊

    举例:

    现在我有两种问候的方式1.helloworld 2.世界你好

    如何简单的实现既可以英文的问候,又可以中式的问候呢?现在有一种简单的实现方案就是使用switch...case 或者使用if语句进行判断然后选择合适的问候方法进行调用。

    现在使用更加简单的方法,可以更好将两种问候结合,那就是将抽象出委托作为上面两种方法的代表,同时作为方法的参数进行传递。

    public void Greet(GreetDelegate greetDelegate ,string name )

    {

      greetDelegate(name);

    }

    public void EnglishSayHello(string name)

    {

      Console.Writeline(name+":"+"HelloWord");

    }

    public void ChineseSayHello(string name )

    {

      Console.Writeline(name+":" +"世界你好")

    }

    如同上面的代码所示,是不是更加的简洁呢。

    4.多播委托

    多播委托也就是发布订阅机制,使用+=和-=,实现订阅和退订

    greetDelegate=ChineseSayHello;

    greetDelegate+=EnglishSayHello;

    注意点:多播委托的时候最好使用的是没有返回值的方法进行订阅,因为多播委托的返回值只有一个,也就是将最后一个订阅的方法的返回值返回回来。

    注意点2:使用+=之前,必须先使用=,否则将出现编译错误(使用了未赋值的局部变量)

    5.匿名方法

    顾名思义就是没有函数名只有函数体的方法,这类方法用来只被调用一次,为了节省代码,使用匿名函数,但是在编译的时候,最终会为这个函数体生成默认的方法名,所以使用匿名函数的影响就是会使的程序变慢,当然这点效率的影响是微不足道的

    举例:

    greetDelegate=delegate(string msg){Console.Writeline(msg);};

    greetDelegate("世界你好");

    6.Lambda表达式

    有了Lambda表达式后,可以更加方便的表示委托,首先对于匿名函数的函数体来说,首先存在一个关键字delegate,显得有些多余,同时还有变量的类型,都显得有些多余,所以在引入了Lambda表达式可以更加简洁的来书写,编译器遵循内部的约定,可以将变量的类型自动进行判断。

    所以将上面的例子进行进一步的修改

    greetDelegate=(ms)=>{Console.Writeline(msg);};

    事件

    事件可以说是一种特殊的委托,它使用关键字event对委托的变量进行封装,使得委托在其类的内部是private,也就是不允许使用=,而是只可以使用开放的接口+=和-=,事件的命名规范:On+名称

    public  Delegate void greetDelegate(string msg);

    public event greetDelegate ongreetDelegate;

    事件机制可以更加完善委托中对于发布订阅的机制,首先保证内部的私有化,禁止使用=,其次不允许订阅者(客户端)发布事件(调用事件),这样会直接报错的,只允许事件的发布者内部调用,将事件发布,订阅者至于允许订阅,符合发布订阅的机制。

    注意:必须保证发布事件之后,一定有订阅事件的,否则将会出现空引用的错误

    举例:

    public Delegate void greetDelegate(string msg);

    public class Publisher

    {

        public event greetDelegate OnGreetDelegate;

        public void  Do()

         {

               //doSomething

              if(OnGreetDelegate!=null)//说明已经有客户端订阅了

              {

                OnGreetDelegate(“有人订阅了事件”);//发布事件,必须保证有订阅的,否则就出问题喽,并且只能发布者内部发布事件哦

              }

         }

    当外部的类进行使用订阅这个事件的时候,只可以订阅,不可以发布,也就是说不可以使用OnGreetDelegate("xxx")

    }

  • 相关阅读:
    BZOJ 4025: 二分图
    20180803 题解 Winniechen's Tesst
    前尘浮华一场梦 NOI2018 游记
    UOJ#311. 【UNR #2】积劳成疾
    欢迎到我的新Blog!
    弹飞大爷 BZOJ4764 LCT维护内向基环树森林
    [SCOI2007]修车 BZOJ1070
    KD-Tree
    CDQ分治
    深入解析DC/OS 1.8 – 高可靠的微服务及大数据管理平台
  • 原文地址:https://www.cnblogs.com/XZhao/p/6368863.html
Copyright © 2011-2022 走看看