委托可以看成是持有一个或多个方法的对象。
1 委托
委托和类一样,是一种用户自定义的类型,类表示的是数据和方法的集合,而委托则 持有 一个或多个方法,以及一系列预定义操作。
通过以下步骤声明委托:
- 使用
delegate
关键字声明委托类型,委托声明与方法声明相似,有返回类型和签名, 只是没有方法主体 - 因为委托是 引用类型,因此有 引用 和 对象。在委托类型声明之后,我们可以声明变量并创建类型的对象,即:
- 使用该委托类型声明一个 委托变量
- 创建委托类型的对象,把它赋值给委托变量。这个委托对象包括指向某个方法的引用,这个引用的方法和第一步定义的签名和返回类型必须要一致
创建委托对象的方式有两种,第一种是使用 new
运算符的对象创建表达式,new
运算符的 操作数 的组成如下:
- 委托类型名
- 一组圆括号,其中包含作为 调用列表 中第一个成员的方法的名字
eg:
delVar = new MyDel(myInstObj.MyM1); // 创建委托并保存引用
另外,快捷语法仅由方法说明符构成,eg:
delVar = myInstObj.MyM1; // 存在隐式转换
整个创建委托例子如:
delegate void MyDel(int value); // 声明委托类型
class Program
{
void PrintLow(int value)
{
Console.WriteLine("{0} - Low Value", value);
}
void PrintHigh(int value)
{
Console.WriteLine("{0} - High Value", value);
}
static void Main()
{
Program = new Program();
MyDel del; // 声明委托变量
Random rand = new Random();
int randomValue = rand.Next(99);
del = randomValue<50 ? new MyDel(program.PrintLow) : new MyDel(program.PrintHigh); // 创建委托对象,并复制给委托变量
del(randomValue);
}
}
1.2 为委托加减方法和组合委托
使用 +
可以组合两个不同的委托成为一个委托
使用 +=
可以为委托添加方法,方法是添加到 调用列表 的最后
同理可以使用 -=
为委托移除方法,-=
运算符从调用列表最后开始搜索
如果委托有返回值并且在调用列表中有一个以上的方法,那么委托只会返回 调用列表 中的最后一个方法返回的数值
2 匿名方法
至此,我们可以使用静态方法或实例方法来初始化委托,即初始化的方法来源 必须 是某个类或结构的成员,然而方法只使用一次即只用来初始化委托,没有必要创建独立的具名方法,这是 匿名方法 允许我明避免使用独立的具名方法。
2.1 匿名方法的语法
可以在以下情况下使用匿名方法
- 声明委托变量时作为 初始化表达式
- 组合委托是在赋值语句的右边
- 为委托增加事件是在赋值语句的右边
匿名方法的语法包括:
delegate
类型关键字- 参数列表,没有可省略
- 语句块
delegate (Paramters) {ImplementationCode}
注意:尽管上述匿名方法中没有显示声明返回值,当其必须返回一个与委托返回类型相同的值,同样的还有签名
2.2 匿名方法中变量和参数的作用域
与委托的具名方法不同,匿名方法可以范围它们外围的作用域的局部变量和环境,外围作用域的变量叫做 外部变量,在匿名方法中实现代码中的外部变量称为 方法捕获,而且只要捕获方法还是委托的一部分,即使变量已经离开作用域,捕获的外部变量也会一直有效。
2.3 Lambda 表达式
通过如下步骤可以把匿名方法转换为 Lambda 表达式:
- 删除
delegate
关键字 - 参数与方法块使用
=>
链接