技术开发 频道

LINQ项目-支持 LINQ 项目的语言功能


【IT168技术文档】

  LINQ 完全构建于通用的语言功能之上,其中某些是在 C# 3.0 和 Visual Basic 9.0 中新增的功能。每个功能都有自己的实用工具,但这些功能共同提供了一种定义查询和可查询 API 的可扩展方法。在本部分中,我们将探究这些语言功能,以及它们如何提供更为直接和声明性的查询模式。

  λ 表达式和表达式树

  许多查询操作符都允许用户提供执行筛选、投影或键值提取的函数。基于 λ 表达式的概念而生成的查询工具为开发人员提供了一种编写函数的简便方法,这些函数可以作为后续计算的参数进行传递。λ 表达式类似于 CLR 委托,它必须符合委托类型定义的方法签名。为了进行说明,我们可以使用 Func 委托类型将上述语句扩展为更为显式的等效形式:
Func filter = s => s.Length == 5; Func extract = s => s; Func project = s => s.ToUpper(); IEnumerable expr = names.Where(filter) .OrderBy(extract) .Select(project);
  λ 表达式是 C# 2.0 匿名方法的自然演化结果。例如,我们可以使用匿名方法编写上述示例,如下所示:
Func filter = delegate (string s) { return s.Length == 5; }; Func extract = delegate (string s) { return s; }; Func project = delegate (string s) { return s.ToUpper(); }; IEnumerable expr = names.Where(filter) .OrderBy(extract) .Select(project);
  总之,开发人员可以自由地将命名方法、匿名方法或 λ 表达式与查询操作符一起使用。λ 表达式的优点是,能够提供最直接而简洁的创作语法。更重要的是,λ 表达式可以编译为代码,也可以编译为数据,从而允许优化器、转换器和计算器在运行时处理 λ 表达式。

  LINQ 定义了一个特殊类型 Expression(在 System.Expressions 命名空间中),该类型用于指示给定 λ 表达式需要表达式树,而不是基于 IL 的传统方法体。表达式树是 λ 表达式的有效内存中数据表示形式,它使表达式的结构透明且显式。

  编译器是发出可执行 IL 还是表达式树取决于 λ 表达式的用法。如果将 λ 表达式指定给委托类型的变量、字段或参数,则编译器将发出与匿名方法等效的 IL。如果将 λ 表达式指定给 Expression 类型的变量、字段或参数,则编译器将发出表达式树。

  例如,请考虑以下两个变量声明:
Func f = n => n < 5; Expression<FUNC> e = n => n < 5;
  变量 f 是对委托的引用,可以直接执行:
bool isSmall = f(2); // isSmall is now true
  变量 e 是对表达式树的引用,不可直接执行:
bool isSmall = e(2); // compile error, expressions == data
  与委托(有效的不透明代码)不同,我们可以像与程序中的任何其他数据结构交互那样与表达式树进行交互。例如,以下程序:
Expression<FUNC> filter = n => n < 5; 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);
  在运行时分解表达式树,并显示以下字符串:

  n LT 5

  对于启用第三方库(利用属于平台一部分的基本查询抽象)的环境,这种在运行时将表达式视为数据的功能很重要。DLinq 数据访问实现利用该功能将表达式树转换为适用于在存储中计算的 T-SQL 语句。
0
相关文章