C# 委托(Lambda表达式)
Lambda表达式
我们刚刚已经看到了,C#2.0引入了匿名方法。然而它的语法有一点冗长,而且需要一些编
译器已经知道的信息。C#3.0引人了Lambda表达式,简化了匿名方法的语法,从而避免包含这
些多余的信息。我们可能会希望使用Lambda表达式来替代名方法。其实,如果先引入了Lambda
表达式,那么就不会有匿名方法。
在匿名方法的语法中,delegate关键字有点多余,因为编译器已经知道我们在将方法赋值给
委托。我们可以很容易地通过如下步骤把匿名方法转换为Lambda表达式:
-
删除delegate关键字;
-
在参数列表和匿名方法主体之间放置Lambda运算符=>。Lambda运算符读作“goes to”。
如下代码演示了这种转换。第一行演示了将匿名方法赋值给变量del。第二行演示了同样的
匿名方法在被转换成Lambda表达式之后,赋值给了变量le1。
MyDel del=delegate(int x) {return x+1;}; //匿名方法
MyDel lel=(int x)=>{return x+1;}; //Lambda表达式
这种简单的转换少了一些多余的东西,看上去更简洁了,但是只省了6个字符。然而,编译
器可以推断更多信息,所以我们可以进一步简化Lambda表达式,如下面的代码所示。
- 编译器还可以从委托的声明中知道委托参数的类型,因此Lambda表达式允许省略类型参
数,如le2的赋值代码所示。
带有类型的参数列表称为显式类型。
省略类型的参数列表称为隐式类型。 - 如果只有一个隐式类型参数,我们可以省略两端的圆括号,如le3的赋值代码所示。
- 最后,Lambda表达式允许表达式的主体是语句块或表达式。如果语句块包含了一个返回
语句,我们可以将语句块替换为return关键字后的表达式,如le4的赋值代码所示。
MyDel del=delegate(int x) {return x+1;}; //匿名方法
MyDel le1= (int x)=>{return x+1;} //Lambda表达式
MyDel le2= (X)=>{return x+1;} //Labbda表达式
MyDel le3= x=>{return x+1;}; //Lambda表达式
MyDel le4= x=> x+1; //Lambda表达式
最后一种形式的Lambda表达式的字符只有原始匿名方法的1/4,更简洁,也更容易理解。
如下代码演示了完整的转换。Main的第一行演示了被赋值给变量del的匿名方法。第二行演
示了被转换成Lambda表达式后的相同匿名方法,它被赋值给变量le1。
delegate double MyDel(int par);class Program
{static void Main(){delegate int MyDel(int x);MyDel del=delegate(int x){return x+1;}; //匿名方法MyDel le1= (int x)=>{return x+1;}; //Lambda表达式MyDel le2= (x)=>{return x+1;};MyDel le3= x=>{return x+1;};MyDel le4= x=> x+;Console.WriteLien($"{del (12)}");Console.WriteLine($"{le1(12)}");Console.WriteLien($"{le2(12)}");Console.WriteLien($"{len3(12)}");Console.WriteLien($"{len4(12)}");}
}
有关Lambda表达式的参数列表的要点如下。
- Lambda表达式参数列表中的参数必须在参数数量、类型和位置上与委托相匹配。
- 表达式的参数列表中的参数不一定需要包含类型(隐式类型),除非委托有ref或Out参
数一一一此时必须注明类型(显式类型)。 - 如果只有一个参数,并且是隐式类型的,则两端的圆括号可以省略,否则必须有括号。
- 如果没有参数,必须使用一组空的圆括号。
图14-16演示了Lambda表达式的语法。