Anonymous Method - Lambda Expression
Lambda表达式是C# 3.0的新特性之一,最简单的Lambda表达式,像这样的:
Func<int,int> f = x => x + 1;
会被编译为一个方法:
int f(int x)
{
return x + 1;
}
所以它和匿名方法的实现很类似,可以说是匿名方法的带类型推导的精简版本。和匿名方法一样,这是一种编译器行为;但是除了更“甜”的语法之外,C# 3.0进一步表现出了不少Functional Programming的特性,虽然还不是很“纯”(大概是受到强类型语言总思路的制约吧)。
和Lambda Expression相关的,C# 3.0还有个叫作Expression Tree的概念。这是它和Anonymous Method所不同的地方,Expression Tree不会被直接编译成一个实际的方法,而是编译成一个类似CodeDOM的语法树。比如:
Expression<Func<int, bool>> exprLambda = x => (x & 1) == 0;
// 请对比:Func<int, bool> nonExprLambda = x => (x & 1) == 0;
会被编译为:
ParameterExpression xParam = Expression.Parameter(typeof(int), "x");
Expression<Func<int, bool>> exprLambda = Expression.Lambda<Func<int, bool>>(
Expression.EQ(
Expression.BitAnd(xParam, Expression.Constant(1)),
Expression.Constant(0)),
xParam);
这个变量exprLambda是一个真正的方法,而不是一个方法指针(delegate/代理)。C# 3.0 Specification:“Following these assignments, the delegate f references a method that returns x + 1, and the expression tree e references a data structure that describes the expression x + 1.”它是方法体本身的描述,就像CodeDOM那样,通过代码描述代码,并且可以被编译、执行(不过这些动作都是透明的)。显然,和CodeDOM一样,你也可以遍历这个树,修改树结点,或者做一些别的特别的事情。这将使C#变得更加动态化(当然cost就是性能低一点点)。
*LINQ
LINQ/DLINQ/XLINQ(以及YLINQ、ZLINQ等等什么LINQ)是基于Lambda语法的。不过这里也存在着大量的语法糖(OK,只要没有带来负面作用那这个词也不是贬义词),比如这句:
from c in customers
join o in orders on c.CustomerID equals o.CustomerID
select new { c.Name, o.OrderDate, o.Total }
等价形式为:
customers.Join(orders, c => c.CustomerID, o => o.CustomerID,
(c, o) => new { c.Name, o.OrderDate, o.Total })
所以*LINQ也是个编译器特性(与CLR无关)?
一切改变都很酷,也确实能提高开发效率,不过我唯一觉得不喜欢的是,C# 3.0一下子引入了这么多的新语法,它已经从一个短小精悍的语言变得越来越复杂了。。
Reference
C# 3.0 Language Specification
http://download.microsoft.com/download/5/8/6/5868081c-68aa-40de-9a45-a3803d8134b8/csharp_3.0_specification.doc
C# 3.0 and LINQ - Expression Trees
http://www.interact-sw.co.uk/iangblog/2005/09/30/expressiontrees