第十三章 委托
- 委托:持有一个或多个方法的对象,在执行委托时会执行它所持有的方法。
- 使用委托经过五个步骤:首先声明委托类型,运用关键字delegate,没有实现代码块;其次,声明委托变量;再者,创建委托对象,并持有方法,方法的参数列表与返回类型与委托相比配,并将委托对象赋值给委托变量;然后,可以增加委托方法,但必须保证与委托参数列表和返回类型一致;最后执行委托对象,这将执行委托所持有的方法。
- 声明委托类型:
delegete void Mydel(int val);//无返回类型
也可以带有返回值,delegete int Mydel(int val);//返回类型为int
- 声明委托变量:
Mydel mydele;
- 创建委托对象:
mydele = new Mydel(myclass.Mythod);
委托方法可以是实例方法也可以是静态方法,而方法可以来自任意的类或者结构。 - 组合委托:使用运算符“+”将具有不同方法的委托组合,创建新的委托,它结合了原来委托的方法,具有原来方法的副本。
- 增加和删除方法:使用运算符“+=”和“-=”可以增加和删除委托方法,注意委托是恒定的,一旦创建便不可改变,增加或删除方法,都会创建新的委托;删除方法时会从调用列表的最后一个开始寻找第一个与实例相匹配的方法并删除之;调用列表中的方法是有顺序的,取决于加入委托对象的顺序。
- 执行委托:
mydele(36);
这个参数将传递给委托所持有的所有方法,当委托持有多个相同的方法时,也会调用这些方法。 - 也可以在声明委托变量的同时将创建的委托对象赋给委托变量
Mydel mydele = new Mydel(myclass.Mythod);
也可以将实例方法或者静态方法直接赋给委托变量:Mydel mydele = myclass.Mythod;
- 委托示例:
//委托基本使用
delegate int Mydel(int val); //声明委托类型
public class Myclass //定义类
{
public int Mythod(int val) //参数列表和返回类型与委托保持一致
{
return val+6;
}
}
Myclass mycl = new Myclass();
Mydel mydele = new Mydel(mycl.Mythod);
mydele(6); //执行委托
Console.WriteLine(mydele(6));
结果会显示12
-
匿名方法:当委托方法只是用一次即用于初始化委托时,可以使用匿名方法。
(1)格式:delegate(参数列表){语句块};注意在语句块后面要有分号,因为它位于赋值语句的右边Mydel mydele = delegate(int val) {return val+6;};
(2)匿名方法的参数列表和返回类型也要与委托保持一致,匿名方法不显示声明返回类型,而是在语句块中体现,包含return语句。
(3)参数:除了数组参数外,匿名方法的参数要在参数数目、参数类型以及位置、修饰符上与委托匹配;可以使用圆括号为空或去掉圆括号简化匿名参数列表,但要求委托没有输出参数且匿名方法参数为空;对于params参数,在委托声明时存在且位于参数列表最后,而在匿名方法的参数列表中去掉修饰符params。
-
Lambda表达式:使用运算符“=>”构建Lambda表达式,以代替匿名表达式。
delegate int Mydel(int val); //声明委托类型
Mydel mydele = new Mydel(mycl.Mythod); //创建委托对象
Mydel mydele = mycl.Mythod; //创建委托对象
Mydel mydele = delegate(int val) {return val+6;}; //使用匿名方法
Mydel mydele = (int val) => {return val+6; } ; //使用Lambda表达式,去掉关键字delegate
Mydel mydele = (val) => {return val+6; } ; //使用Lambda表达式,去掉类型int
Mydel mydele = val => {return val+6; } ; //使用Lambda表达式,去点圆括号
Mydel mydele = val => val+6 ; //最简Lambda表达式
当然上述使用Lambda表达式的方式要求只有一个参数并且是隐式类型的,圆括号可以省略。
- 带有返回值的委托:若委托带有返回值且持有一个以上的方法时,委托的返回值取调用列表中最后一个方法的返回值,其余方法的返回值将会被忽略。
- 带有引用参数的委托:若委托含有引用参数且持有多个方法,则调用下一个方法时,上一个方法运算结果得到的参数值会传递给下一个方法。
//带有引用参数的委托
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace test21
{
delegate int Mydel(ref int val); //声明委托类型
public class Myclass //定义类
{
public int Mythod(ref int val) //参数列表和返回类型与委托保持一致
{
return val+6;
}
}
class Program
{
static void Main(string[] args)
{
Myclass mycl = new Myclass();
Mydel mydele = new Mydel(mycl.Mythod);
int value = 6;
mydele(ref value); //执行委托
Console.WriteLine(mydele(ref value));
}
}
}
结果还是12。