实际上,使用 Expression.Compile 将是 慢点 如果你只需要创建 一 宾语。但是,如果你缓存创建者函数,从长远来看它会更快,因为lambda性能会很好。
Expression.Compile
这是代码:
static Func<TArg, T> CreateCreator<TArg, T>() { var constructor = typeof(T).GetConstructor(new Type[] { typeof(TArg) }); var parameter = Expression.Parameter(typeof(TArg), "p"); var creatorExpression = Expression.Lambda<Func<TArg, T>>( Expression.New(constructor, new Expression[] { parameter }), parameter); return creatorExpression.Compile(); }
Func<TArg, T> creator = CreateCreator<TArg, T>();
有了这个,你可以使用 creator(arg) 用于创建新对象 T 。
creator(arg)
T
三种方式的小基准:
class Program { static void Main(string[] args) { // warm up Test1<Class1>(0); Test2<int, Class1>(0); const int numiter = 10000; var sw1 = Stopwatch.StartNew(); for (int i = 0; i < numiter; i++) Test1<Class1>(i); sw1.Stop(); Console.WriteLine($"With Activator.CreateInstance: " + $"{(double)sw1.ElapsedTicks / numiter} ticks per object"); var sw2 = Stopwatch.StartNew(); for (int i = 0; i < numiter; i++) Test2<int, Class1>(i); sw2.Stop(); Console.WriteLine($"With Expression.Compile: " + $"{(double)sw2.ElapsedTicks / numiter} ticks per object"); var sw3 = Stopwatch.StartNew(); var creator = CreateCreator<int, Class1>(); for (int i = 0; i < numiter; i++) creator(i); sw3.Stop(); Console.WriteLine($"With cached Expression.Compile: " + $"{(double)sw3.ElapsedTicks / numiter} ticks per object"); } static public object Test1<T>(params object[] parameters) { var instance = (T)Activator.CreateInstance( typeof(T), BindingFlags.Instance | BindingFlags.Public, null, parameters, null); return instance; } static Func<TArg, T> CreateCreator<TArg, T>() { var constructor = typeof(T).GetConstructor(new Type[] { typeof(TArg) }); var parameter = Expression.Parameter(typeof(TArg), "p"); var creatorExpression = Expression.Lambda<Func<TArg, T>>( Expression.New(constructor, new Expression[] { parameter }), parameter); return creatorExpression.Compile(); } static public object Test2<TArg, T>(TArg arg) { var creator = CreateCreator<TArg, T>(); return creator(arg); } }
在我的机器上生成以下结果(发布模式/ Visual Studio外部):
With Activator.CreateInstance: 3.0739 ticks per object With Expression.Compile: 494.0388 ticks per object With cached Expression.Compile: 0.1097 ticks per object