最近学习了msil,发现了不少好玩的,今天介绍一个用IL来建立对象的方式c#
public static T Create<T>() where T : new() { return new T(); } public static object CreateNative() { return new object(); }
写一个测试帮助方法简单的测试下这两个方法的执行时间的长短:工具
public static void Measure(string what, int reps, Action action) { action(); //warm up double[] results = new double[reps]; for (int i = 0; i < reps; i++) { Stopwatch sw = Stopwatch.StartNew(); action(); results[i] = sw.Elapsed.TotalMilliseconds; } Console.WriteLine("{0} - AVG = {1}, MIN = {2}, MAX = {3}", what, results.Average(), results.Min(), results.Max()); }
调用测试方法:学习
int reps = 5; int its = 100000; Measure("create", reps, () => { for (int i = 0; i < its; i++) { Create<object>(); } }); GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Measure("createNative", reps, () => { for (int i = 0; i < its; i++) { CreateNative(); } });
执行结果:测试
能够经过测试结果看出来本地方法建立的比泛型方式建立的消耗的时间短,这是为何。用工具查看生成的il就能够发现为何了。
泛型方式生成的IL以下:
本地方式的生成IL以下:
能够看出泛型方式生成的IL里面调用了Activator.CreateInstance方法,而本地方式而直接new一个对象。因此本地方式的生成对象要比泛型方式用时短。既然这样直接经过Activator.CreateInstance 生成对象呢。ui
public static object CreateReflect(Type type) { return Activator.CreateInstance(type); }
如今再来比较这三种的生成方式的用时长短,用一样的方式调用CreateReflect,获得结果以下:
从结果上看能够看出最快的是本地直接new,第二快是经过Activator.CreateInstance,最慢的则是泛型实例化建立对象。
在工做中泛型建立对象很常见。如何解决泛型建立对象慢的问题呢?pwa
public class CreationHelper<T> where T : new() { public static Func<T> objCreator = null; public static T New() { if (objCreator == null) { Type objectType = typeof(T); ConstructorInfo defaultCtor = objectType.GetConstructor(new Type[] { }); DynamicMethod dynMethod = new DynamicMethod( name: string.Format("_{0:N}", Guid.NewGuid()), returnType: objectType, parameterTypes: null); var gen = dynMethod.GetILGenerator(); gen.Emit(OpCodes.Newobj, defaultCtor); gen.Emit(OpCodes.Ret); objCreator = dynMethod.CreateDelegate(typeof(Func<T>)) as Func<T>; } return objCreator(); } }
用以上相同的方式来测试,测试代码:3d
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); Measure("DynamicCreate", reps, () => { for (int i = 0; i < its; i++) { CreationHelper<object>.New(); } });
测试结果以下:
结果一目了然,IL方式建立对象的用时在本地实例化和Activator.CreateInstance之间,只比本地实例化稍慢。因此泛型实例化能够考虑这种方式,能够提高泛型实例化的效率。code
本文介绍了c#建立对象的4种方式,简单的比较了这四种建立效率。说明了IL的效率果真是高。学会了高效的建立泛型对象的一种方式。orm