委托delegate
之前学过的任何类型,不管是值类型还是引用类型,其变量都可以进行赋值,或者作为方法的参数进行传递,而如何引用方法或者把方法作为参数进行传递呢?这就需要用到委托-delegate.
申明方法
委托也是一种类型,它与类一样,需要我们自己来定义。一种类型的方法
委托的定义如下:
delegate 返回值类型 委托类型名 (参数)
例如:
delegate void GreetDelegate(string name);
定义时委托类型的返回值和参数与要引用的方法的返回值和参数一致,二者在外形上一样,只是委托用delegate修饰.
委托的使用分以下三步:
1.委托声明
2.委托实例化
3.委托调用
Greeting greet;
greet = ChineseGreet;
Greeting engGreet = new Greeting(EnglishGreet);
委托类似于函数指针,但与函数指针不同的是,委托是面向对象的、类型安全的和保险的。委托既能引用静态方法,也能引用实例方法。
委托是一个类,它定义了方法的类型,使得可以将方法当做另一方法的参数来进行传递,也即是方法的参数是一个委托变量,在调用此方法时,就可以把一个方法做为参数传递给委托变量;
委托对象的一个有用属性是:可以使用 + 运算符将多个对象分配给一个委托实例。多播委托包含已分配委托的列表。在调用多播委托时,它会按顺序调用列表中的委托。 注意:只能合并相同类型的委托。
当委托绑定多个有返回值的方法时,其结果是最后绑定的那个方法的返回值,前面绑定方法的返回值会被最后绑定方法的返回值所覆盖,所以使用委托时一般不带返回值.
一、委托和所引用的方法必须保持一致:
1.参数个数、类型、顺序必须完全一致。
2.返回值必须一致。
二、一个委托被同时映射到静态方法和实例方法,并分别返回特定的信息。
其它四种形式的委托
委托变量在绑定方法时,是把方法名赋值给了委托变量名,这样就需要在类里面定义方法,而有些方法只用到了一次,这样的方法在类里面过多时,程序的可读性就不是太好,针对这种情况,可以使用匿名委托,即不用在类里面额外定义方法.
delegate定义的匿名委托
格式:
delegate(参数){
要执行的代码
};
参数:相当于绑定方法的参数{};里面相当于绑定方法的方法体由于是赋值,是一个语句,后面的;不要省
lambda表达式
格式:
(参数)=>{
要执行的代码
};
参数:相当于绑定方法的参数{};里面相当于绑定方法的方法体由于是赋值,是一个语句,后面的;不要省
Func委托
格式:
Func<int,int,int> s =delegate(int,int){
return int;
};
使用Func泛型,前面两个是参数类型,最后一个是返回值类型,其变量可以绑定匿名委托,lambda表达式和相同类型的方法,此种委托一定会有返回值;
Action委托
格式:
Action<string> action=delegate(string){
};
使用Action泛型,<>里面的类型是参数的类型,该种委托可以绑定匿名委托,lambda表达式和方法,但其一定没有返回值.
事件event
委托也是一种类型,根据面向对象编程的特性,通常会把一个类型的变量封装到类的内部,并把其设置成private的,然后通过属性来访问该变量,所以在实际编程时委托类型也会定义在类里面.
使用event关键字来修饰委托变量,其本质上是委托变量的属性.
在类的内部,不管声明它是public还是protected,他总是private的。即在类的外部,不能够用“=”直接给属性赋值,需用注册“+=”和注销“-=”的访问限定符与声明事件时使用的访问限定符相同。
发送(或引发)事件的类称为“发行者”,接收(或处理)事件的类称为“订阅者”。事件的触发必须在发行者内部,在客户端是不能触发的.
由事件的特性引发出了一种设计模式-观察者设计模式,该设计模式是为了定义对象间的一种一对多的依赖关系,以便于当一个对象的状态改变时,其他依赖它的对象会被自动告知并更新,该设计模式包含以下两个类:
被监视对象:它往往包含其他对象所感兴趣的内容;
监视者:用来监视被监视对象,当被监视对象触发事件时,监视者能自动接收事件.
自己的理解:
委托或是事件申明都分三个部分:
委托者;委托;执行委托者;
如果 委托者 和 执行委托者 都是类,那么
委托者:委托的申明(也可以写在类之外);事件的申明;委托触发方法;
委托:写在类外面;
委托执行者:符合委托的执行方法
调用的时候
委托:
实例化委托;
为委托进行和委托方法的绑定(可使用加减法);
调用委托类的触发方法;
事件
实例化委托类;
为事件进行和委托方法的绑定(只能使用+= or -=);
调用委托类的触发方法;