什么是Lambda表达式?
Lambda表达式为编写匿名方法提供了更简明的函数式的句法,但结果却在编写LINQ查询表达式时变得极其有用,因为它们提供了一个非常紧凑的而且类安全的方式来编写可以当作参数来传递,在以后作运算的函数。
与那匿名方法其实效果是差不多的,只是语法上不同表现形式不同而已。在行内实现预期代理和匿名代理的内容的一种方式。
我们先来看个例子
public class UserInfo
{
public int Id { set; get; }
public string UserName { set; get; }
public int Age { set; get; }
}
using System;
using System.Collections.Generic;
using System.Text;
using System.Data.Linq;
using System.Linq;
class Program
{
static void Main(string[] args)
{
List<UserInfo> list = new List<UserInfo> {
new UserInfo{Id=1,UserName="zhang",Age=18},
new UserInfo{Id=2,UserName="lisi",Age=20},
new UserInfo{Id=3,UserName="wangsan",Age=25}
};
var users = list.Where(u => u.Age > 18);//使用Lambda表达式 Where 扩展方法
//使用匿名方法 两者效果出来是一样的 但你说哪个简洁呢?
//var users = list.Where(
// delegate(UserInfo u)
// { return u.Age > 18; }
// );
foreach (var u in users)
Console.WriteLine("年龄大于18的用户:"+u.UserName);
}
}
输出大于18的用户
如上u => u.Age > 18 就是一个Lambda表达式
在C#里,一个lambda表达式在句法上是写成一个参数列表,随后是 => 符号,随后是表达式在调用时要运算的表达式或者语句块.
语法:params => expression
在单个参数的Lambda表达式中我们可以省略参数列表部分的小括号,但是多个参数或者没有参数以及需要显式地为参数设置数据类型的情况下,小括号就不能省略!!!
分析: u => u.Age > 18
接收一个参数 u 并要求返回年龄大于18的 UserInfo对象(集合),这参数命名可自定义。有人或许会问你那u都没指定
类型你怎么知道他是UserInfo类型的?lambda表达式不需要像匿名方法那样显示指定类型,它会根据用法来推断出类型,
这好比这参数u 编译器推断出u参数属于UserInfo类型,因为当前的Where扩展方法的对象是个范型的List<UserInfo>集合
Lambda参数的类型可以在编译时和被Visual Studio的intellisense引擎推断出来,这意味着在编写lambda时你将获得完全的intellisense 和编译时检查 在VS中就能感受到 你压根儿没指定类型 但它可以智能提示该参数的属性,说起来还真有点“神奇”。
如果一定要给他加类型的话 可以这样写 var users = list.Where((UserInfo u) => u.Age > 18); 效果一样。就是多几个字节而已。。。。
Expressions Tree
Expressions Tree 是什么?可以理解成是Lambda表达式的一种数据结构。虽然有点了解 但不知道可在应用到哪里。
需引用System.Linq.Expressions命名空间
Expression<TDelegate>类共有四个属性:
TDelegate表示委托的类型
-
Body:获取表达式的主体;
- Parameters:获取Lambda表达示的参数;
- NodeType:得到树中某些节点的表达式类型(ExpressionType),这是一个有45种不同值的枚举类型,代表表达式节点的所有可能类型,如返回常数、也可能返回参数、或者返回一个值是否小于另外一个(<),或者返回一个值是否大于另外一个(>),或者返回两个值的和(+)等等;
- Type:得到表达式的静态类型,在本例中,表达式的类型是Func<int, int, int>。
测试一下
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
namespace Lambda
{
class Program
{
delegate int MyDelegate1(int y);//定义一个委托类型
static void Main(string[] args)
{
Expression<MyDelegate1> lambda = y => y + 1;
Console.WriteLine("body:{0} nodeType:{1} params:{2} type:{3}", lambda.Body, lambda.NodeType, lambda.Parameters, lambda.Type);
//输出body:y+1 nodeType:Lambda params:System.Linq.Expressions.ParameterExpression
//type:Lambda.Program+MyDelegate1
// 可以看出是在描述我那个Lambda表达式
}
}
}
例子2
static void Main(string[] args)
{
//使用泛型委托
Expression<Func<int,int,int>> lambda = (a, b) => a * b;
Console.WriteLine(">>>>{0}", lambda.Compile().Invoke(2, 3));
//lambda.Compile()将表达目录数描述的Lambda转换成可执行的代码,如上也就是转换成Func<int,int,int>
//Invoke()方法调用委托方法
输出>>>6
//结论 Expression 不是可执行代码 它只是基于Lambda结构的目录描述,而真正执行的是他Compile的代码
}