自C#3.0开始,就有了一种把实现代码赋予委托的新语法:Lambda表达式。只要有委托参数类型的地方,就可以使用Lambda表达式。它可以包含表达式和语句,并且可用于创建委托或表达式树类型。

C#的Lambda表达式都使用Lambda运算符 =>,该运算符读为“goes to”。

从许多方面,Lambda表达式都可以看作是C# 2的匿名函数的一种演变。匿名函数能做的几乎一切事情都可以用Lambda表达式来完成。

从显式的形式来看,Lambda与匿名函数相似,Lambda表达式有特殊的转换规则:表达式的类型本身并非委托类型,但它可以通过多种方式隐式或显式地转换成一个委托实例。

一. Lambda表达式的形式

(1)Lambda表达式最冗长的形式是:

(显示类型参数列表) => {语句}

例如:

Func<string, int> returnLength;
returnLength = (string text) => {return text.Length;};

Console.WriteLine(returnLength("Hello World!"));

其中,(string text) => {return text.Length;}部分用于创建委托实例的表达式。

(2)用单一表达式作为主体的Lambda表达式:

我们目前是用一个完整的代码块来返回值,可以在代码块中放入多个语句,可以指定循环等,这和匿名函数是一样的。

然而在大多数时候,都可以用一个表达式来表示整个主体,该表达式的值是Lambda的结果。格式如下:

(显示类型参数列表) => 表达式

在上面的例子中,意味着Lambda表达式可以写成:

(string text) => text.Length;

(3)隐式类型的Lambda表达式:

格式如下:

(隐式类型的参数列表) => 表达式

隐式类型的参数列表是一个以逗号分隔的名称列表,没有类型。但隐式和显式的参数不能混合匹配——要么整个列表都是显式类型的,要么全部都是隐式类型的。除此之外,如果有任何out或ref参数,就只能使用显式类型。

所以上面的例子中的Lambda表达式还可以写成:

(text) => text.Length;

(4)单一参数的快捷语句的Lambda表达式:

如果Lambda表达式只需一个参数,而且那个参数可以隐式指定类型,语法如下:

参数名 => 表达式

因此上面的例子的Lambda表达式可以写成:

text => text.Length;

(5) 没有参数的Lambda表达式:

没有参数的Lambda表达式格式如下:

() => 表达式

二. Lambda表达式转换成表达树

.NET3.5的表达树是对象构成的树,树中的每个节点本身都是一个表达式。不同表达式类型代表能在代码中执行的不同操作:二元操作、一元操作、方法调用、构造函数调用等。

一个简单的表达式如下:

Expression firstArg = Expression.Constant(2);
Expression secondArg = Expression.Constant(3;
Expression add = Expression.Add(firstArg, secondArg);

Console.WriteLine(add);

用Lambda表达式创建表达式树:

Expression <Fun<int>> return 5 = () => 5;
Fun<int> compiled = return5.Compile();
Console.WriteLine(compiled());

并非所有Lambda表达式都能转换成表达式树,不能将带有一个语句块(即使只有一个return语句)的Lambda表达式树。只有对单个表达式进行求值的Lambda才可以转换成表达式树,而且该表达式树不能包含赋值操作,因为在表达式树种表示不了这种操作。

本文作者:子匠_Zijor,转载请注明出处:http://www.dengzhr.com/others/backend/csharp/651