先看一个例子:
-
Expression<Func<
string
,
bool
>> expr = o => o.Length > 10;
初次接触Lambda表达式的人可能会被搞迷糊,这样的语句到底是什么意思,怎么样工作,原理又是什么。
逐级分析以上语句,分为两个部分,以等号为界。
第一部分是变量类型的申明:Expression<Func<string, bool>>
expr,表示expr这个变量是一个Lambda表达式,这个表达式符合这样的一种委托:bool DelegateName(string
obj)。
第二部分是表达式的声明o => o.Length >
10
,这个“=>”是Lambda操作符,读作“转到”,必须把=>左右看成是一个整体,因为这实际是一个匿名方法,“=>”左边是方
法传入参数的申明,右边是函数体,如果用常规的表示方法,可以写成如下形式:
-
bool
MethodName(
string
o)
-
{
-
return
o.Length > 10;
-
}
仔细观察两部分拆解以后的形式其实不难发现,第一部分的工作是定义了一个匿名的委托,而第二部分则是符合这个匿名委托的一个方法,由于这个方法没有明确给定名称,因此称为匿名方法。
那么,expr到底又是什么样的东西。有一点必须明确的是,expr表示绝对不是这个匿名方法的返回值,而是这个匿名方法中所有表达式的
System.Linq.Expressions.Expression形式。也就是说,在expr中,这个函数体里所有的表达式已经被拆解成一个一个的
单元,每一个单元都是一种System.Linq.Expressions.Expression的派生类。由于表达式和表达式之前存在着上下级的关系,
因此所有的表达式呈现一种树状结构,称为表达式树。
一个匿名方法是如何转换为表达式树的呢?这个问题其实不用太过关心,因为C#编译器在对程序编译的时候已经将上述第二部分的内容自动转换为相应的表达式树了。上述例子中编译的结果通过Reflector反编译出来的内容如下所示:
-
ParameterExpression CS$0$0000;
-
Expression<Func<
string
,
bool
>> expr = Expression.Lambda<Func<
string
,
bool
>>(Expression.GreaterThan(Expression.Property(CS$0$0000 = Expression.Parameter(
typeof
(
string
),
"o"
), (MethodInfo) methodof(
string
.get_Length)), Expression.Constant(10,
typeof
(
int
))),
new
ParameterExpression[] { CS$0$0000 });
-
这串代码看起来有点糊,我把代码梳理了一下使得它更容易读,如下所示:
-
Expression<Func<
string
,
bool
>> expr;
-
-
-
ParameterExpression paramExpr = Expression.Parameter(
typeof
(
string
),
"o"
);
-
-
PropertyInfo propInfo =
typeof
(
string
).GetProperty(
"Length"
, BindingFlags.Instance | BindingFlags.Public);
-
-
MemberExpression memberExpr = Expression.Property(paramExpr, propInfo);
-
-
ConstantExpression constExpr = Expression.Constant(10,
typeof
(
int
));
-
-
BinaryExpression greaterThanExpr = Expression.GreaterThan(memberExpr, constExpr);
-
-
expr = Expression.Lambda<Func<
string
,
bool
>>(greaterThanExpr, paramExpr);
-
是不是好麻烦啊?呵呵,好在这些工作已经在编译的时候完成了,不需要我们手工创建,除非你想动态创建表达式。关于如何动态创建表达式,我在这里就先不详细说明了,将在下一博里再详述。
综上所述,对待Lambda表达式,最基本一个原则是不要把表达式看成了语句的运算结果,而应该看成这些语句本身,也就是把语句作为对象来处理。语句和语句之间通过表达式树来关联,而从语句转换为表达式树已由编译器自动完成,不需要人工介入。
在下一篇文章中,我将会对表达式树和语句的对应关系,以及如何动态构造表达式进行一些说明,敬请期待。
分享到:
相关推荐
进度条.Lambda表达式.匿名方法.委托.类.集合.初始化.容易懂
Lambda 表达式(C# 编程指南).docLambda 表达式(C# 编程指南).docLambda 表达式(C# 编程指南).doc
《精通Lambda表达式:Java多核编程》
视频地址:https://www.bilibili.com/video/BV1ut411g7E9 【Java8】Lambda表达式 和 Stream API 详解笔记 md文档
668.666.JAVA基础教程_动态代理与Java8新特性-Lambda表达式使用举例(668).rar
2_Lambda表达式.zip2_Lambda表达式.zip2_Lambda表达式.zip
java8 lambda表达式在集合中的使用,包含代码例子。
Stream、Lambda表达式练习.doc
什么是Linq表达式什么是Lambda表达式.pdf 什么是Linq表达式什么是Lambda表达式.pdf
主要介绍了解决mybatis-plus3.1.1版本使用lambda表达式查询报错的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
内容概要:python、lambda表达式的用法举例。 采用.txt 文本格式。无需解压,直接使用。 总结了lambda表达式的六种常见用法: 1.命名使用 2.与map()、 filter()和 reduce()等高阶函数配合 3.赋予key参数使用 4.直接...
通过多个示例详细演示了.Net中C#语言lambda表达式的基本用法,主要包括三个方面内容: 1.什么是lambda表达式 2.理解lambda表达式 3.使用lambda表达式
Java8新特性初级入门学习
例如,在addUser()方法中使用了Lambda表达式(name, age) -> new User(name, age)来创建一个新用户对象并将其添加到用户列表中;在updateUser()方法中使用了Lambda表达式user -> user.setAge(age)来更新用户的年龄...
写法:所有Lambda表达式都使用Lambda运算符=>,该运算符读作”goes to”。Lambda运算符的左边是输入参数(如果有),右边是表达式或语句块。Lambda表达式x => x * x读作”x goes to x times x”。 注:(左边)输入参数...
Java8发布到现在至少3年了,但是对Lambda表达式不熟悉、看不懂、不会用的现象非常常见。 即使是升级到JDK1.8了,但是很多开发者依然是停留在1.8之前的开发方式,使用的也是非常老旧和过时的API,遇到函数式接口也是...
C++中lambda表达式详解与原理分析.pdf
maskList.sort((Mask o1, Mask o2) -> o1.getBrand().compareTo(o2.getBrand())); 这里使用的sort方法的参数类型是Comparator,我们就是把Lambda表达式作为Comparator传入sort方法中的。Comparator就是一个函数式...
● lambda表达式语法 ● 流与管道的基本操作 ● 使用收集器与汇聚来终止管道 ● 创建流 ● 分割迭代器、fork/join框架与异常 ● 使用微基准测试检查流的性能 ● 使用默认方法演化API 目录 第1章 走进新生代...
java8新特性,Lambda表达式........