2012-02-26 54 views
8

我有这样的表达:编译的表达式树木误解?

Expression<Func<string, bool>> f = s => s.Length < 5; 

enter image description here

ParameterExpression p = Expression.Parameter (typeof (string), "s"); 
MemberExpression stringLength = Expression.Property (p, "Length"); 
ConstantExpression five = Expression.Constant (5); 
BinaryExpression comparison = Expression.LessThan (stringLength, five); 
Expression<Func<string, bool>> lambda= Expression.Lambda<Func<string, bool>> (comparison, p); 

//让:测试

Func<string, bool> runnable = lambda.Compile(); 
Console.WriteLine (runnable ("kangaroo")); // False 
Console.WriteLine (runnable ("dog")); //True 

我想请教一下.Compile()

是什么编制?第一次执行与后期执行之间有什么区别?

编译应该发生的事情一次,不得再发生....

什么/它是如何帮助我?

+4

你用什么工具生成这个表达式树图图片? – Anastasiosyal 2012-02-26 14:12:04

+2

@Anastasiosyal它从一本书http://i.stack.imgur.com/Y5ejU.jpg – 2012-02-26 14:38:42

+1

啊,我明白了,我以为我失踪了片刻一些伟大的Visualiser的。我猜,@ gcvcdcamp也有[wpf表达式树可视化工具](http://www.codeproject.com/Articles/83465/ExpressionTree-Visualizer-in-WPF)。一个有趣的项目可能是使用类似[Graph#](http://graphsharp.codeplex)的方式将表达式树渲染为图形。虽然我可以看到这样的图表如何能够随着任何不重要的表达式迅速变得非常忙碌。 – Anastasiosyal 2012-02-26 14:49:35

回答

9

当你正在构建在运行时表达式树没有发出代码。这是在运行时表示.NET代码的一种方式。

一旦您在表达式树上调用.Compile方法,就会发出实际的IL代码,将此表达式树转换为您可以在运行时调用的委托(您的案例中的Func<string, bool>)。所以这个表达式树代表的代码只有在你编译它之后才能被执行。

调用编译是昂贵的操作。基本上你应该调用一次,然后缓存你​​可以用来多次调用代码的结果委托。

+0

我将使用哪种“REAL”场景?好吧...所以即时建立表达式在运行时,但它更难,并将包含大量的IF(构建它)....你可以请真正的场景编辑我需要动态地建立一个表达式? – 2012-02-26 21:12:53

+0

你是怎么表达第一个陈述的?你的意思是第一个例子中的所有5行代码都没有IL代码,但会直接转换成表达式树?我不相信编译器会做这样的优化。 – Euphoric 2012-02-27 09:34:05

2

Expression<Func<string,bool>>仅是表达的表示,它不能执行。拨打Compile()会为您提供已编译的委托,您可以调用一段代码。本质上,您的程序在运行时组成一小段代码片段,然后像编译器处理它一样调用它。这就是代码的最后两行:你可以看到,编译后的代码段可以分析你传入的字符串的长度 - 当长度小于5时,你会得到一个True;当它是五个或更多时,你会得到一个False

的编译代码段的第一次执行,会发生什么是平台相关的,而不应使用.NET平台的程序员被检测到。

2

Compile()获取表达式树(这是一些逻辑的数据表示)并将其转换为IL,然后可以直接执行作为代表。

第一执行后来执行之间的唯一区别是,Compile()不会触发从IL到本地处理器代码JIT编译的可能性。 可能会在第一次执行时发生