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 和表达式 Lambda 非常相似,只是语句被包含在大括号内: ```csharp (input parameters) => {statement;} ``` 大括号中的语句可以是任意多条,也可以写成多行。 类型猜测 当编写一个 Lambda 表达式的...
Lambda表达式也可以用于创建`Expression`对象,这对于构建表达式树非常有用。表达式树是一种表示代码结构的数据结构,常用于动态查询,如LINQ to SQL。例如: ```csharp using System.Linq.Expressions; ...
在C#中,`System.Linq.Expressions`命名空间提供了一系列类用于创建和操作表达式树。例如,`Expression<TDelegate>`用于创建表示特定委托类型的表达式树,`LambdaExpression`表示可被编译并执行的lambda表达式,`...
在C#编程中,表达式树(Expression Tree)是一种数据结构,它以树的形式表示了程序中的表达式。表达式树对于理解代码逻辑、编译器优化、动态代码执行以及 LINQ 查询等场景有着重要的作用。本教程将深入探讨表达式树...
4. **编译表达式**:使用`Expression.Lambda`和`Compile`方法将表达式树编译成委托,这样可以在运行时执行。 5. **执行深拷贝**:对原始对象调用编译后的委托,生成新的对象实例,完成深拷贝。 以下是一个简化的...
通过学习和掌握LINQ及Lambda表达式,开发者能够更高效地处理数据,无论是内存中的集合还是远程数据库,从而提高代码的可读性和维护性。在实际项目中,合理运用这些技术能显著提升开发效率和代码质量。
在C#或VB.NET中,`System.Linq.Expressions`命名空间提供了构建和操作表达式树的类。这些表达式树在运行时可以被分析、修改和执行,为动态语言运行时(DLR)提供支持。 在文章中,作者可能介绍了以下关键知识点: 1....
在C#编程中,表达式树(Expression Trees)和反射是两种重要的技术,它们在处理动态行为和元数据方面有着广泛的应用。本压缩包文件包含了多个小程序,这些程序旨在帮助开发者理解和运用这两种技术,特别是在回答问答...
在上面的代码中,我们声明了一个表达式目录树,表示一个Lambda表达式,参数为n和m,返回值为n*m+2。 2. 编译表达式目录树 使用Compile()方法可以将表达式目录树编译为可执行代码,例如: ```csharp Func, int, ...
这些转换可能涉及到解析Lambda表达式树,识别其组成部分(如参数、运算符和方法调用),然后映射到相应的数据库查询或Web服务请求结构。 测试是确保此类转换正确性的关键部分,因此"TestConsole"项目可能是一个简单...
例如,可以使用正则表达式处理简单的字符串表达式,或者使用`System.Linq.Expressions`命名空间中的类来构建和解析更复杂的表达式树。 **表达式树** `Expression Trees`是C#中用于表示可执行代码的数据结构,它们...
最后,`Expression.Lambda`方法被用来将这些二元表达式包装成一个lambda表达式,该lambda表达式接受两个`T`类型的参数,并返回一个布尔值。 在`Main`方法中,我们看到了`Generate<T>`方法的实际应用。首先,我们...
`Expression`类及其子类提供了构建和操作表达式树的方法。在我们的例子中,我们可能需要使用`Expression.Convert`方法来改变表达式的返回类型。 下面是一个简单的示例,展示了如何进行这种转换: ```csharp using ...
总之,"ExpressionTreeApp"项目提供了一个实用的示例,展示了如何利用C#的表达式树和Lambda表达式实现动态查询。这种技术在各种需要动态生成查询逻辑的场景中,如Web API、RESTful服务或任何需要根据输入参数生成...
10. 表达式树(Expression trees) 表达式树是一种表示代码结构的数据结构,它允许开发者将表达式作为数据来操作。这在动态生成代码时尤其有用,例如在表达式可以作为参数传递到方法中的情况下。 以上介绍的知识点是...
Lambda表达式的语法形式为`(parameters) => expression`,其中`parameters`是输入参数,`expression`是计算结果的表达式。 - Lambda表达式转换:编译器会将lambda表达式转换为适当的委托类型或表达式树。 - 类型...
- C# 提供了 `System.Linq.Expressions` 命名空间,其中的表达式树类可以用来表示C#的lambda表达式。表达式树是数据结构,能表示代码的结构,非常适合用于编译运行时的动态表达式。 5. **编译和执行表达式**: - ...
然而,要动态获取参数名称和值,我们需要利用反射(Reflection)和表达式树(Expression Trees)这两个强大的工具。 **反射(Reflection)**是.NET框架的一个特性,它允许程序在运行时检查自身的信息,如类型、属性...
#### Lambda 表达式和 Lambda 表达式树(Lambda Expressions and Lambda Expression Trees) Lambda表达式是一种简洁地定义匿名函数的方法,常用于定义短小的函数或作为委托类型的参数。 ##### Lambda 表达式的...