C#中几种建立对象的方式的对比

最近学习了msil,发现了不少好玩的,今天介绍一个用IL来建立对象的方式c#

1.最多见的两种建立对象方式

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以下:
本地方式生成的IL
能够看出泛型方式生成的IL里面调用了Activator.CreateInstance方法,而本地方式而直接new一个对象。因此本地方式的生成对象要比泛型方式用时短。既然这样直接经过Activator.CreateInstance 生成对象呢。ui

2.Activator.CreateInstance方式生成对象

public static object CreateReflect(Type type)
        {
            return Activator.CreateInstance(type);
        }

如今再来比较这三种的生成方式的用时长短,用一样的方式调用CreateReflect,获得结果以下:
三种方式
从结果上看能够看出最快的是本地直接new,第二快是经过Activator.CreateInstance,最慢的则是泛型实例化建立对象。
在工做中泛型建立对象很常见。如何解决泛型建立对象慢的问题呢?pwa

3.使用IL来建立泛型对象

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

4.总结

本文介绍了c#建立对象的4种方式,简单的比较了这四种建立效率。说明了IL的效率果真是高。学会了高效的建立泛型对象的一种方式。orm

相关文章
相关标签/搜索