一、委托定义与声明
委托定义:
1、委托是一种数据类型,就像类是一种数据类型一样是一种可用于封装命名或匿名方法的引用类型。是定义方法签名的类型注意:在方法重载的上下文中,方法的签名仅指形参(参数的类型和个数)。 但在委托的上下文中,方法签名不仅包括形参还包括返回值。
2、委托对象是一个有序方法的列表。它所封装的方法具有相同的返回值类型和参数列表,这些方法可以是实例方法也可以是静态方法,可以来自任何类或结构。
3、方法的列表称为调用列表。
委托类型的声明:
委托类型的声明与方法的声明类似,只是在方法返回值类型前添加了关键字delegate。
访问修饰符 delegate 返回值类型 委托类型名(形参列表)
例如:public delegate void MyDel(int x);
因为委托在编译的时候会被编译成类,所以在任何可以声明类的地方都可以声明委托。任何委托都隐式继承于类MultiDelegate,所以在本质上委托是一个类。但自定义的一个类不能显示继承于类MultiDelegate
二、声明委托对象并实例化
MyDel delvar=new MyDel(myInstObj.Method1);
等价于
MyDel delvar= myInstObj.Method1;此为快捷语法
注释:@1、执行以上语句后,方法myInstObj.Method1为调用列表中的第一个方法。
@2、能使用快捷语法是因为在方法名和其相应的委托类型间有隐式转换。
通过将委托与命名方法或匿名方法关联,可以实例化委托。必须使用具有兼容返回类型和输入参数的方法或 lambda 表达式实例化委托。 当实例化委托时,可以将其实例与任何具有兼容签名的方法相关联。 然后就可以通过委托实例调用方法。
三、 通过调用委托实例调用委托列表中的方法
1、 可以像调用方法一样调用委托(只是将方法名换为委托实例),例如delvar(55)
2、 当委托被调用时,它使用被调用是的相同参数类调用调用列表中的每个方法。
3、 如果一个方法在调用列表中出现多次。那么当调用委托是,每次在列表中遇到这个方法是它都会被调用一次。
4、 如果委托有返回值,那么调用列表中最后一个方法的返回值是委托的返回值。其他方法的返回值都被忽略
5、 如果委托有引用参数,那么在调用委托列表中下一个方法时此引用参数的值不是初始值而是上一个方法中对此引用参数修改后的值。
四、 委托的各种操作
1、 利用运算符=为委托对象赋值
Mydel delvar=myInstObj.MyM1;
delvar=Sclass.otherM2;执行此句后,委托delvar中不再包含方法myInstObj.MyM1。
注释:由于委托是引用类型,所以可以通过给它赋值来改变包含在委托变量中的引用。旧的委托对象会被垃圾回收器回收。
2、利用运算符+ 组合委托
Mydel delA=inst.M1; Mydel delB=sclass.M1;
Mydel delc=delA+delB;
3、 利用运算符+=为委托增加或绑定方法或另一个委托
Mydel delA=inst.M1; Mydel delB=sclass.M1;
delA+=delB;delA+=inst.M2;
4、 利用运算符-=从委托中移除一个方法。
5、 判断委托是否为空
由于委托为引用类型,所以只需将委托实例与Null值进行比较即可。
注意:在实例化委托对象时,可通过两种方式
1、使用New运算符。
MyDel delvar=new MyDel(myInstObj.Method1);
2、使用快捷语法。
MyDel delvar= myInstObj.Method1;
但开始让委托的调用列表为空时只能使用快捷语法,即delvar=Null;
使用MyDel delvar=new MyDel();会编译错误,提示MyDel没有0个参数的方法重载。
注意:在声明完一个委托实例但没有对其赋值时,不能使用运算符+=和-=为委托绑定或解绑方法。即要使用运算符+=和-=为委托绑定或解绑方法,必须确保给委托实例的调用列表中含有方法(使用=将委托实例赋值为NUll的情况除外)