如果要運行以下代碼
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慢得多。這是預期的結果嗎?是否有可能以某種方式重寫表達式來獲得等效的代碼,但哪個更快?
您的委託f是使用已編譯的生成類創建的,其中字段e的類型為E,訪問值如下所示:
return <Target>.e.V;
在第二種情況(表達式)中,使用常量指令創建委託,該指令使用Closure作為目標,其中對像數組,其中e是第一個元素。代碼可以表示如下:
return ((E)<Target>.Constants[0]).V;
這就是為什麼第一種情況下性能更好的原因。
注意:在Visual Studio中使用“Watch window”,當您調試代碼時,可以檢查“f.Target”和“ef.Target”來確認它。