委托
大约 3 分钟
委托
委托是持有一个或多个方法的对象;
执行委托就是执行它所持有的方法;
委托声明以delegate开头,有返回类型和签名,没有主体;
委托是类型声明,不能声明在类内部;
声明委托类型----声明委托变量----创建委托对象----为委托对象增加方法----调用委托
委托的调用列表
- 调用列表指委托中所包含的方法的列表;
- 调用列表的方法必须具有相同的签名和返回类型;
- 调用列表的方法可以是实例方法或者静态方法;
- 调用委托时会执行其调用列表中所有的方法。
声明委托类型
delegate void MyDel(int x);
创建委托对象
//变量声明
MyDel delVar1 ,dVar2;
// 1.使用new运算符创建委托对象,圆括号内为调用列表中第一个成员的方法的名字
delVar1 = new MyDel ( myClass.Fun1 );
delVar2 = new MyDel ( MyClass.Fun2 );
// 2.使用快捷语法创建委托对象
delVar1 = myClass.Fun1;
delVar2 = MyClass.Fun2;
// 3.使用初始化方法创建委托变量同时创建委托对象
MyDel delVar1 = myClass.Fun1;
MyDel delVar2 = new MyDel ( MyClass.Fun2 );
给委托赋值
- 委托属于引用类型,可以给委托赋值来改变包含在委托变量中的引用。
添加方法
通过委托组合能够为委托添加方法,使用 += 运算符;
从委托移除方法,使用 -= 运算符;
移除方法从委托末尾开始移除第一个匹配项;
调用空委托会抛出异常,可以与null进行比较判定委托是否为空。
MyDel delVal = myClass.Fun1; delVal += myClass.Fun2; delVal -= MyClass.Fun1;
组合委托
委托组合能连接多个委托并创建一个新的委托;
委托是恒定的,委托对象一旦创建就不能被改变;
示例:
MyDel delC = delA + delB
调用委托
- 调用带返回值的委托:只会返回调用列表中最后一个方法的返回值,其他方法的返回值将被忽略。
- 调用带引用参数 ref 的委托:在调用委托列表中的下一个方法时,参数的新值会传递给下一个方法,而不是参数的初始值。
匿名方法和 Lambda 表达式
- 匿名方法语法:
delegate (Type p1,...){ImplementationCode};
- Lambda 表达式语法:
(Type p1,...) => {ImplementationCode};
- Lambda 表达式取消了匿名方法中的 delegate 关键字,在参数表和主体块之间插入Lambda运算符;
- Lambda 表达式可直接替代匿名方法,代码更简洁;
- 参数表可以使用隐式类型(取消参数类型符),编译器从委托参数类型中获取:
(x,y) => {...}
- 如果只有一个隐式类型,可以省参数表的圆括号:
x => {...}
- 如果没有参数,则必须使用空的圆括号:
() => {...}
- 如果只有一个语句且作为返回值,则可以省略大括号:
x => x+1
- 如果委托有ref或out参数,则必须使用显式类型;
- lambda表达式可以访问表达式块外部的变量;
- 在lambda表达式中修改闭包的值时,可以在表达式外部访问已改动的值;
- 给多个线程使用闭包可能遇到并发冲突;