3 语言级特性支撑下的LINQ项目(Language Features Supporting the LINQ Project)
LINQ 完全建立在用途广发的(general-purpose)语言级特性上,其中一部分是 C# 3.0 和 Visual Basic 9.0 新加的特性。每一种特性都有其特有的作用,不过把这些特性加起来就能提供一条可扩展的定义查询方法或者可查询的API的途径。本章节我们来探究这些语言级的特性,看看它们是怎样实现更加直观的声明式的查询处理的。
3.1 Lambda表达式和表达式树(Lambda Expressions and Expression Trees)
很多查询操作符允许用户提供一种可以执行过滤(filtering)、发送数据(projection)和分解出Key值(key extraction)这样的功能。这样的查询技巧建立在lambada表达式的概念之上,它提供给开发者一条方便的途径来写这样的函数,可以为后来的附值(subsequent valuation)像传递参数一样来传递。Lambda表达式跟 CLR 委托(delegates)很相似,必须依托在由一个委托类型(delegate type)定义的方法名(method signature)之上。为了举例说明这个问题,我们可以分解上面的代码片段,使用函数式委托类型(Func delegate type)来实现与之对等的(equivalent)而且更加直观的代码:
Func<string, string> extract = s => s;
Func<string, string> project = s => s.ToUpper();
IEnumerable<string> expr = names.Where(filter)
.OrderBy(extract)
.Select(project);
Lambda表达式是 C# 2.0 的匿名方法(anonymous methods)的自然演进(natural evolution)。举例来说,我们可以用匿名方法来写上面的例子如下所示:
return s.Length == 5;
};
Func<string, string> extract = delegate (string s) {
return s;
};
Func<string, string> project = delegate (string s) {
return s.ToUpper();
};
IEnumerable<string> expr = names.Where(filter)
.OrderBy(extract)
.Select(project);
一般来说,开发者通过查询操作符(query operators)使用已命名的方法(named methods)、匿名的方法(anonymous methods)、或者lambda表达式(lambda expressions)都是很自由的。Lambda表达式胜过给创造者提供最直接最紧凑的语法,更重要的是,lambda表达式可以像代码或数据一样编译,使得它可以被优化器(optimizers)、编译器(translators)和运算器(evaluators)在运行时(runtime)处理。
LINQ 定义了一个卓越的类型(distinguished type),Expression (在System.Expressions 命名空间里),指出一个特定的lambda表达式比一个传统的IL-based方法实体(method body)更加需要表达式树(expression tree)。表达式树是更有效率的表现lambda表达式在内存中的数据(in-memory data),使得表达式的数据结构(structure)更加清晰(transparent and explicit)。
编译器决定是否生成可执行的IL(executable IL)还是一个表达式树(expression tree)的条件,在于lambda表达式是如何使用的。当lambda表达式赋予一个委托类型(delegate type)的变量(variable)、field或参数(parameter)时,编译器生成与匿名方法(anonymous method)同样的IL。当lambda表达式赋予一个Expression类型的变量(variable)、field或参数(parameter)时,编译器就将它替换成一个表达式树(expression tree)。
举例来说,分析下面的两个变量的声明方式:
Expression<Func<int, bool>> e = n => n < 5;
变量 f 是一个委托类型的变量,可以直接像如下执行:
变量 e 是一个表达式树类型的变量,不能像如下方式执行:
与委托方式不同的,我们可以把有效率但不透明的代码(effectively opaque code)与表达式树(expression tree)相配合使用,就像程序代码中其他数据结构(data structure)一样。举例如下的程序:
BinaryExpression body = (BinaryExpression)filter.Body;
ParameterExpression left = (ParameterExpression)body.Left;
ConstantExpression right = (ConstantExpression)body.Right;
Console.WriteLine("{0} {1} {2}",
left.Name, body.NodeType, right.Value);
虚拟机在运行时分解这些表达式并输出如下结果:
在运行时像使用 data 一样使用这些表达式的能力是危险的,它会授权一个使用第三方库的系统(ecosystem of third-party libraries)可以影响(leverage)平台内部(part of the platform)的基础查询提取功能(base query abstractions)。DLinq数据存取(data access)的实现在存储区(in the store)通过调整这个技巧(leverages this facility)来把表达式树转换成适合赋值(suitable for evaluation)的 T-SQL 语句(statement)。
相关推荐
● lambda表达式语法 ● 流与管道的基本操作 ● 使用收集器与汇聚来终止管道 ● 创建流 ● 分割迭代器、fork/join框架与异常 ● 使用微基准测试检查流的性能 ● 使用默认方法演化API 目录 第1章 走进新生代...
Stream、Lambda表达式练习.doc
2_Lambda表达式.zip2_Lambda表达式.zip2_Lambda表达式.zip
Java8发布到现在至少3年了,但是对Lambda表达式不熟悉、看不懂、不会用的现象非常常见。 即使是升级到JDK1.8了,但是很多开发者依然是停留在1.8之前的开发方式,使用的也是非常老旧和过时的API,遇到函数式接口也是...
主要介绍了解决mybatis-plus3.1.1版本使用lambda表达式查询报错的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
lambda表达式和递归算法
适用人群 本源码资源适用于具备一定Java编程基础的开发人员和学习者。...2、函数式接口与Lambda表达式:学习如何使用Lambda表达式与不同类型的函数式接口进行交互,并了解如何通过Lambda表达式实现函数的传递和组合
Microsoft Visual Studio.Net(VS2010)编写的lambda表达式语法控制台程序。
通过多个示例详细演示了.Net中C#语言lambda表达式的基本用法,主要包括三个方面内容: 1.什么是lambda表达式 2.理解lambda表达式 3.使用lambda表达式
Java8的lambda表达式
用于将将字符串转换为lambda表达式,对于实时获取运算结果或界面筛选条件,很有帮助
简单的一些lambda表达式的测试代码,可用来学习简单的一些lambda表达式的测试代码,可用来学习
Lambda表达式之集合操作,代码里主要针对java 集合list的操作
C#将Lambda表达式转成Sql语句,根据自己看的文章手写出来的,并配有自己理解的注释,有需要的同学可以自行下载。
java lambda表达式,lambda 表达式基本上表达了函数式接口的实例(具有单一抽象方法的接口称为函数式接口。一个例子是 java.lang.Runnable)。lambda 表达式实现了唯一的抽象函数,因此实现了函数式接口 lambda ...
精通lambda表达式:Java多核编程,使用lambda表达式和流的最佳实践
Stream和Lambda表达式是Java 8引入的两个重要特性,它们极大地简化了集合处理和函数式编程的复杂性。以下是关于Stream和Lambda表达式的最佳实践介绍: Lambda表达式 Lambda表达式允许我们以简洁的方式表示匿名函数...
Lambda表达式浅析
lambda表达式与表达式树