委托和事件

委托

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")

}

posted @ 2017-02-05 23:25  善良的小赵  阅读(231)  评论(0编辑  收藏  举报