编译表达树误会了吗?

时间:2012-02-26 13:07:55

标签: c# .net-4.0 expression-trees

我有这个表达:

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);

// let:test

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

我想问一下.Compile()

它是什么编译的?第一次执行与后期执行之间有什么区别......?

编译应该是一次发生的事情,而不是以后再发生......

什么/它对我有什么帮助?

3 个答案:

答案 0 :(得分:10)

在运行时构建表达式树时,不会发出任何代码。这是一种在运行时表示.NET代码的方法。

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

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

答案 1 :(得分:2)

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

首次执行编译片段时会发生什么情况取决于平台,使用.NET平台的程序员无法检测到。

答案 2 :(得分:2)

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

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