自3.5版本以来,.NET以及微软的.NET语言开始支持表达式树。它们为这些语言的某个特定子集提供了eval形式的求值功能。考虑下面这个简单的Lambda表达式:

 Func<int, int, int> add = (x, y) => x + y;

可以知道,上述代码最后生成一个局部函数。Lambda表达式是需要编译的代码。在C#编译器运行时,把匿名函数转换为IL代码。为了建立一个表达式树,需要对上述语法稍作修改:

Expression<Func<int, int, int>> addExpr = (x, y) => x + y;

唯一的差别是保存Lambda表达式的变量的类型。这个差别指示C#编译器生成完全不同的代码。编译器不是把表达式编译成IL代码,进行加法运算,而是自动生成一段代码,这段代码可以创建复杂的对象层级结构。对象的类型全部都是从System.Linq.Expressions.Expression派生出来的。

由于保存addExpr变量中的值是Lambda表达式的一个抽象表示,因此它不可以直接执行。但是.Net Framework可以在运行时编译一个表达式树:

Func<int, int, int> addCompiled = addExpr.Compile();

C#函数式程序设计之分析表达式

把代码看成数据这个思想的主要动理论是它允许我们在运行时分析代码。有时,这个想法的动机是了解代码的执行过程,但是,它也允许我们在运行时把代码转换为最适合于当前任务的执行格式。

表达式树使用了语法树中十分常见的一种结构。层级中包含的每个元素都派生自一个公用的基类,每个类型都需要一个派生类。同时,公用基类有一个枚举类型字段,在进行任何类型转换之前,利用这个字段进行类型检查。

在实际应用中,分析表达式树的目的是把表达式树转换为不同的格式,但是它们表示同一个或同类表达式。考虑下面这个LINQ表达式:

var peopleWithInTheirName =
from p in people
where p.Name.Contains("i")
select p;

这个简短的查询要在people集合中查找所有由Name属性返回的字符串中有i的元素。对于LINQ,C#编译器把像这个例子的查询表达式转换为一系列的方法调用,把where字句转换为Lambda表达式:

p => p.Name.Contains("i");

这个表达式接受一个对象p,然后返回针对这个对象的某个条件是否成立。这种类型的表达式被称为谓词。.NET Framework专门为这些表达式预定义了一个委托类型,即Predicate<T>:

Predicate<Person> nameContainsI = p => p.Name.Contains("i");

Predicate<T>在功能上等效于Func<T , bool>:接受类型为T的一个项为参数,返回一个bool值表示这个给定的T参数是否满足某个条件。

下面是一个用递归算法求阶乘的简单函数:

static int Fact(int x)
{
int result = 1;
for (int i = 2 ; i <= x; i++)
result *= i;
return result;
}

如果使用Lambda表达式:

Func<int, int> Fact = x =>
{
int result = 1;
for (int i = 2; i <= x; i++)
result *= i;
return result;
};

表达式树的核心是运行时处理代码——不管是需要理解和分析代码,或者动态生成代码。

C#函数式程序设计之代码即数据的更多相关文章

  1. C#函数式程序设计之用闭包封装数据

    如果一个程序设计语言能够用高阶函数解决问题,则意味着数据作用域问题已十分突出.当函数可以当成参数和返回值在函数之间进行传递时,编译器利用闭包扩展变量的作用域,以保证随时能得到所需要的数据. C#函数式 ...

  2. C#函数式程序设计之泛型(下)

    C#函数式程序设计之泛型(下)   每当使用泛型类型时,可以通过where字句对泛型添加约束: + 这个例子直观地声明了一个约束:类型T必须与ListItem<string>相匹配.泛型类 ...

  3. C#函数式程序设计之函数、委托和Lambda表达式

    C#函数式程序设计之函数.委托和Lambda表达式 C#函数式程序设计之函数.委托和Lambda表达式   相信很多人都听说过函数式编程,提到函数式程序设计,脑海里涌现出来更多的是Lisp.Haske ...

  4. C#函数式程序设计之惰性列表工具——迭代器

    有效地处理数据时当今程序设计语言和框架的一个任务..NET拥有一个精心构建的集合类系统,它利用迭代器的功能实现对数据的顺序访问. 惰性枚举是一个迭代方法,其核心思想是只在需要的时候才去读取数据.这个思 ...

  5. Entity Framework 程序设计入门二 对数据进行CRUD操作和查询

    前一篇文章介绍了应用LLBL Gen生成Entity Framework所需要的类型定义,用一行代码完成数据资料的读取, <LLBL Gen + Entity Framework 程序设计入门& ...

  6. C#函数式程序设计之局部套用与部分应用

    函数式设计的核心与函数的应用以及函数如何作为算法的基本模块有关.利用局部套用技术可以把所有函数看成是函数类的成员,这些函数只有一个形参,有了局部套用,才有部分应用.部分应用是使函数模块化成为可能的两个 ...

  7. 我终于理解了LISP『代码即数据|数据即代码』的含义

    以前我一直不能理解LISP里引用的作用,感觉引用和字符串没什么区别.比如:> (define (func)     'ok) > (func) 'ok 这里把引用ok当做了函数func的返 ...

  8. C#函数式程序设计之泛型

    Intellij修改archetype Plugin配置 2014-03-16 09:26 by 破狼, 204 阅读, 0 评论,收藏, 编辑 Maven archetype plugin为我们提供 ...

  9. C#函数式程序设计之泛型(上)

    在面向对象语言中,我们可以编写一个元素为某个专用类型(可能需要为此创建一个ListElement)的List类,或者使用一个非常通用.允许添加任何类型元素的基类(在.NET中,首先想到的是System ...

随机推荐

  1. JAVA生产者消费者的实现

    春节回了趟老家,又体验了一次流水席,由于桌席多,导致上菜慢,于是在等待间,总结了一下出菜流程的几个特点: 1.有多个灶台,多个灶台都在同时做菜出来. 2.做出来的菜,会有专人用一个托盘端出来,每次端出 ...

  2. 关于 c# 操作 world

    把数据存放在datatable 中并循环取出来数据然后再保存在world中 protected void ExportToWord(DataSet Ads) { try { Object Nothin ...

  3. <《巴菲特之道 (第三版)》>读书笔记

    以便宜的价格买入长期绩优的股票 他把对公司的投资看做是拥有公司的一部分股权,看重的是公司的长期经济价值 别人越是草率,我们越要加倍慎重 如果你发现自己已经在陷阱中,最重要的是想办法让自己不要再往下陷 ...

  4. 使用proxool 连接池:No suitable driver found for proxool

    使用proxool连接池时:报错误No suitable driver found for proxool.shide的原因: ①.WEB-INF目录下的lib中没有proxool连接池jar驱动包. ...

  5. 利用VBA查找excel中一行某列第一次不为空与最后一列不为空的列数

    昨日同事有需求,想知道每个商品第一次销售的月份,以及最后一次销售的月份. 本想通过什么excel函数来解决,但是找了半天也没找到合适的,最后还是通过VBA来解决吧. 使用方法: Excel工具-宏-V ...

  6. win10上安装Docker

    方法1:具体我没有试过,不知道win10下可以么.http://blog.csdn.net/zistxym/article/details/42918339 方法2: 先安装VirtualBox(下载 ...

  7. cmd窗口编码方式的修改

    cmd默认的编码是采用GBK   regedit HKEY_CURRENT_USER\Console\%SystemRoot%_system32_cmd.exe\CodePage 十进制:936 GB ...

  8. 使用jQuery开发iOS风格的页面导航菜单

    在线演示1 本地下载     申请达人,去除赞助商链接 iOS风格的操作系统和导航方式现在越来越流行,在今天的jQuery教程中,我们将介绍如何生成一个iphone风格的菜单导航. HTML代码 我们 ...

  9. C# 开发者代码审查清单【转】

    这是为C#开发者准备的通用性代码审查清单,可以当做开发过程中的参考.这是为了确保在编码过程中,大部分通用编码指导原则都能注意到.对于新手和缺乏经验(0到3年工作经验)的开发者,参考这份清单编码会很帮助 ...

  10. wamp2.5 不能运行在win2003的解决方法

    安装时提示 httpd.exe 不是有效的 win32程序 之后就启动不了,连小icon都不显示了 经查发现 wampserver 2.5用 vc11编译,并使用了他的类库 vc11是不支持 xp和 ...