在很早以前就听说过表达式树了,但并没有去了解它。虽然自己用过linq to sql和linq to entity,但也就用着就用着,并没有去深究c#代码怎么会生成sql代码而不是IL。废话不多说了,开写吧!

.net里表达式树核心概念就是:将代码作为数据。它将一些代码表示为一个对象树,树中的每个节点本身都是一个表达式,不同的表达式类型代表能在代码中执行不同操作:二元操作,一元操作,方法调用等等。

  System.Linq.Expressions命名空间包含了代表表达式的各个类。所有的表达式类都从Expression类派生,Expression是个抽象类,主要包含的是一些静态的方法,这些方法用于生成其他表达式类的实例。Expression类还包含了两个重要属性:

  1.Type属性:代表了表达式求值结果的类型。比如,一个表达式是要获取一个字符串的Length属性,那么该表达式的Type属性应为int类型

  2.NodeType属性:代表了表达式的种类。这个种类表示成ExpressionType枚举的一个成员:LessThan,Invoke,Multiply,MemberAccess等等(有80几种,汗!)。

一个表达式树的简单例子

    static void Main(string[] args)
{
Expression firstArg = Expression.Constant();
Expression secondArg = Expression.Constant();
Expression add = Expression.Add(firstArg, secondArg); Console.WriteLine(add);

输出结果:

上面的代码将会生成如下图的表达式树:

值得注意的是,表达式中“叶”表达式在代码中是最先创建的:表达式是自下而上构建的。这是由“表达式不易变”这一事实实现的。

将表达式树编译成委托

LambdaExpression是从Expression派生的类型。泛型类Expression<TDelegate>是从LambdaExpression派生的,其中泛型参数TDelegate必须是委托类型。

LambdaExpression有个Compile方法能创建恰当类型的一个委托。而Expression<TDelegate>的Compile方法返回TDelegate类型的委托。来看看下面的例子:

    static void Main(string[] args)
{
Expression firstArg = Expression.Constant();
Expression secondArg = Expression.Constant();
Expression add = Expression.Add(firstArg, secondArg); Expression<Func<int>> func = Expression.Lambda<Func<int>>(add);
Func<int> compiled = func.Compile();
Console.WriteLine(compiled());
}

我们通过Expression.Lambda<TDelegate>(Expression expression)方法来创建Expression<TDelegate>类型对象,再调用其Compile方法获取表达式树编译出的委托实例。

将C# Lambda表达式转换成表达式树

我们知道Lambda表达式能显示或隐式地转换成恰当的委托实例。但是,编译器也能很轻松的将Lambda表达式构建为一个表达式树:

//将Lambda表达式转换成表达式树
Expression<Func<int>> return5 = () => ;

但是,并不是所有的Lambda表达式都能转换成表达式树,有一些限制:不能将带有一个语句块的Lambda转换成一个表达式树-----只有对单个表达式进行求值得Lambda才可以。表达式中不能包含赋值操作,因为表达式树中表示不了这种操作。还有其他一些较少见的限制,总而言之,如果存在转换问题,你会在编译时发现。

位于Linq核心的表达式树

表达式树可以说是Linq的核心之一,为什么是Linq的核心之一呢?因为表达式树使得c#不再是仅仅能编译成IL,我们可以通过c#生成一个表达式树,将结果作为一个中间格式,在将其转换成目标平台上的本机语言。比如SQL。我们常用的Linq to sql就是这样生成SQL的。

下图展示了Linq to Objects和Linq to SQL的不同路径:

资料参考于《深入理解c#》第二版

C#表达式树的初步了解的更多相关文章

  1. C# 高性能对象映射(表达式树实现)

    前言 上篇简单实现了对象映射,针对数组,集合,嵌套类并没有给出实现,这一篇继续完善细节. 开源对象映射类库映射分析 1.AutoMapper 实现原理:主要通过表达式树Api 实现对象映射 优点: . ...

  2. C# 表达式树讲解(一)

    一.前言 一直想写一篇Dpper的定制化扩展的文章,但是里面会设计到对Lambda表达式的解析,而解析Lambda表达式,就必须要知道表达式树的相关知识点.我希望能通过对各个模块的知识点或者运用能够多 ...

  3. C# 表达式树遍历(二)

    一.前言 上一篇我们对表达式树有了初步的认识,这里我们将对表达式树进行遍历,只有弄清楚了他的运行原理,我们才可以对他进行定制化修改. 表达式系列目录 C# 表达式树讲解(一) C# 表达式树遍历(二) ...

  4. 再讲IQueryable<T>,揭开表达式树的神秘面纱

    接上篇<先说IEnumerable,我们每天用的foreach你真的懂它吗?> 最近园子里定制自己的orm那是一个风生水起,感觉不整个自己的orm都不好意思继续混博客园了(开个玩笑).那么 ...

  5. [C#] C# 知识回顾 - 表达式树 Expression Trees

    C# 知识回顾 - 表达式树 Expression Trees 目录 简介 Lambda 表达式创建表达式树 API 创建表达式树 解析表达式树 表达式树的永久性 编译表达式树 执行表达式树 修改表达 ...

  6. 轻量级表达式树解析框架Faller

    有话说 之前我写了3篇关于表达式树解析的文章 干货!表达式树解析"框架"(1) 干货!表达式树解析"框架"(2) 干货!表达式树解析"框架" ...

  7. 用五分钟重温委托,匿名方法,Lambda,泛型委托,表达式树

    这些对老一代的程序员都是老生常谈的东西,没什么新意,对新生代的程序员却充满着魅力.曾经新生代,好多都经过漫长的学习,理解,实践才能掌握委托,表达式树这些应用.今天我尝试用简单的方法叙述一下,让大家在五 ...

  8. LinqToDB 源码分析——处理表达式树

    处理表达式树可以说是所有要实现Linq To SQL的重点,同时他也是难点.笔者看完作者在LinqToDB框架里面对于这一部分的设计之后,心里有一点不知所然.由于很多代码没有文字注解.所以笔者只能接合 ...

  9. LinqToDB 源码分析——生成表达式树

    当我们知道了Linq查询要用到的数据库信息之后.接下就是生成对应的表达式树.在前面的章节里面笔者就已经介绍过.生成表达式树是事实离不开IQueryable<T>接口.而处理表达式树离不开I ...

随机推荐

  1. 信息安全系统设计基础exp_2

    详见搭档20135322郑伟博客,链接如下:http://www.cnblogs.com/zhengwei0712/p/4971435.html

  2. C#本质论读书笔记:第一章 C#概述|第二章 数据类型

    第一章 1.字符串是不可变的:所有string类型的数据,都不可变,也可以说是不可修改的,不能修改变量最初引用的数据,只能对其重新赋值,让其指向内存中的一个新位置. 第二章 2.1 预定义类型或基本类 ...

  3. 数据挖掘系列(4)使用weka做关联规则挖掘

    前面几篇介绍了关联规则的一些基本概念和两个基本算法,但实际在商业应用中,写算法反而比较少,理解数据,把握数据,利用工具才是重要的,前面的基础篇是对算法的理解,这篇将介绍开源利用数据挖掘工具weka进行 ...

  4. 如何在WPF中引用Windows.System.Forms.Integration

    转自 http://www.cnblogs.com/sinozhang1988/archive/2012/11/28/2792804.html “未找到程序集 WindowsFormsIntegrat ...

  5. java内存优化牛刀小试

    小猿做了两年的c++,上个月竟然被调到java项目,于是第一篇随笔就想八一八java的内存优化. 首先优化这种事,肯定是应该放到最后去做的,不过在写代码的过程中养成良好的习惯也是很重要的.在这里先推荐 ...

  6. Matrix67大牛推荐的省选知识点

    时间复杂度(渐近时间复杂度的严格定义,NP问题,时间复杂度的分析方法,主定理)排序算法(平方排序算法的应用,Shell排序,快速排序,归并排序,时间复杂度下界,三种线性时间排序,外部排序)数论(整除, ...

  7. 转-JS中document对象详解

    对象属性 document.title //设置文档标题等价于HTML的<title>标签 document.bgColor //设置页面背景色 document.fgColor //设置 ...

  8. [转]SQL注入攻防入门详解

    原文地址:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html =============安全性篇目录============ ...

  9. iOS开发小技巧--UIScrollView内部子控件添加约束的注意点

    注意:用UIScrollView时布局子控件的时候,不要相对于UIScrollView来添加约束,这样做不是设置子控件的位置,反而是设置了UIScrollView的contentSize 子控件的尺寸 ...

  10. java.lang.NoClassDefFoundError: javax/transaction/UserTransaction

    在运行定时任务的时候报错: Java.lang.NoClassDefFoundError: javax/transaction/UserTransaction 原因:缺少jta的jar包 解决方法:下 ...