如果要运行following code
using System;
using System.Linq.Expressions;
using System.Diagnostics;
public class E
{
public double V { get; set; }
}
public class Program
{
public static void Main()
{
E e = new E();
Func<double> f = () => e.V;
Expression expr = Expression.Property(Expression.Constant(e), "V");
Expression<Func<double>> exp = Expression.Lambda<Func<double>>(expr);
Func<double> ef = exp.Compile();
e.V = 123;
int attempts = 5;
for (int j = 0; j < attempts; j++)
{
int c = 100000;
double[] r1 = new double[c];
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < c; i++)
{
r1[i] = f();
}
sw.Stop();
double[] r2 = new double[c];
Stopwatch sw2 = new Stopwatch();
sw2.Start();
for (int i = 0; i < c; i++)
{
r2[i] = ef();
}
sw2.Stop();
double rat = (double)sw.ElapsedTicks / sw2.ElapsedTicks;
Console.WriteLine(rat);
}
}
}
然后事实证明编译的表达式比lambda慢得多。这是预期的结果吗?是否有可能以某种方式重写表达式以获得相同的代码,但哪种代码能够更快地运行?
答案 0 :(得分:3)
您的委托f是使用已编译的生成类创建的,其字段e的类型为E,访问值如下:
return <Target>.e.V;
在第二种情况(表达式)中,使用常量指令创建委托,该指令使用Closure作为目标,其中对象数组为e,即第一个元素。代码可以这样表示:
return ((E)<Target>.Constants[0]).V;
这就是为什么第一种情况下表现更好的原因。
注意:使用&#34;观看窗口&#34;在Visual Studio中,当您调试代码时,您可以检查&#34; f.Target&#34;和&#34; ef.Target&#34;确认一下。