匿名方法
-
前面的情况是方法被某个结构或者类的成员, 可以调用方法
-
如果方法只调用一次, 用来实例化委托, 在这种情况下, 除了创建委托的语法需要, 没有必要创建独立的具名方法, 使用匿名方法即可
-
匿名方法是实例化委托时内联声明的方法.
class Program
{
delegate int OtherDel(int InParam);
static void Main()
{
//匿名方法
OtherDel del = delgate(int x){return x + 20;};
Console.WriteLine($"{del(5)}");
Console.WriteLine($"{del(6)}");
}
}
(1)使用匿名方法
可以在如下地方使用匿名方法
-
声明委托变量时作为初始化表达式
-
组合委托时在赋值语句的右边
-
为委托增加事件时在赋值语句的右边
(2)匿名方法的语法
匿名方法包含如下部分
-
delegate
关键字 -
参数列表, 如果语句块没有使用任何参数则可以省略
-
语句块, 匿名方法的代码
delegate(argList)
{
statement
};
A.返回类型
匿名方法不会显式声明返回值, 然而, 实现代码本身的行为必须通过返回一个与委托的返回类型相同的值来匹配委托的返回类型, 如果委托没有返回值, 匿名方法就不能返回值
//声明有返回值委托
delegate Type MyDelegate(argList);
//声明匿名方法
MyDelegate myDelegate = delegate(argList)
{
return NotVoidMethod();
};
//声明无返回委托
delegate void MyDelegate(argList);
//声明匿名方法
MyDelegate myDelegate = delegate(argList)
{
voidMethod();
};
B.参数
除了数组参数, 匿名方法的参数列表必须在如下3方面与委托匹配
-
参数数量
-
参数类型及位置
-
修饰符
可以通过圆括号为空, 或者省略圆括号, 来简化匿名方法的参数列表, 但必须满足如下两个条件
-
方法的参数列表不包含任何
out
参数 -
匿名方法不用任何参数
-
用于简化, 和委托的参数列表无关
delegate void SomeDel(int x);
SomeDel SDel = delegate
{
Console.WriteLine("hi");
}
C.params参数
如果委托声明的参数列表包含了params参数, 那么匿名的方法的参数列表将被忽略params关键字
delegate void SomeDel(int x, params int[] Y);
SomeDel mDel = delegate(int X, int[] Y)
{
...
}
(3)变量和参数的作用域
参数以及声明在匿名方法内部的局部变量的作用域限制在实现代码的主体内
A.外部变量
与委托的具体方法不同, 匿名方法也可以访问他们外围作用域的局部变量和环境
-
外围作用域的变量叫做外部变量
-
用在匿名方法实现代码中的外部变量被称为方法捕获
B.方法捕获变量的声明周期的扩展
-
只要方法捕获变量是委托的一部分, 即使变量已经离开了作用域, 方法捕获外部变量也会一直有效
-
由于匿名方法在委托的环境里保留的方法捕获变量, 当委托执行时候, 变量也可以在委托中使用
2、Lambda表达式
-
使用Lambda表达式来替代匿名方法
-
如果先引入了Lambda表达式, 就不会有匿名方法
匿名方法转换为Lambda表达式步骤
-
删除delegate关键字
-
在参数类表和匿名方法主体之间防止哦Lambda运算符, Lambda运算符读作goes to
MyDel del = delgate(int x){return x + 1;};
MyDel del = (int x) => {return x + 1;};
进一步简化Lambda表达式
-
编译器还可以从委托的声明中知道委托参数的类型, 因此Lambda表达式允许省略类型参数
-
带有类型的参数列表称为显式类型
-
省略类型的参数列表称为隐式类型
-
-
如果只有一个隐式类型参数, 可以省略两端的括号
-
Lambda允许表达式的主体是语句块或表达式, 如果语句块包含了一个返回语句, 可以将语句块替换为return关键字后的表达式
MyDel del = delgate(int x){return x + 1;};
MyDel le1 = (int x) => {return x + 1;};
MyDel le2 = (x) => {return x + 1;};
MyDel le3 = x => {return x + 1;};
MyDel le4 = x => x + 1;
关于Lambda表达式的参数列表要点
-
Lambda表达式的参数列表中的参数必须在参数数量、类型和位置上与委托相匹配
-
表达式的参数列表中不一定需要包含类型(隐式类型), 除非委托有ref和out参数, 此时必须注明类型(显式类型)
-
如果只有一个参数, 并且是隐式类型的, 则两端的圆括号可以省略, 否则必须有括号
-
如果没有参数, 必须使用一组空的圆括号