快速创建对象而不是 Activator.CreateInstance(type) [英] Fast creation of objects instead of Activator.CreateInstance(type)

查看:24
本文介绍了快速创建对象而不是 Activator.CreateInstance(type)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力提高应用程序的性能.我们有很多 Activator.CreateInstance 调用引起了一些麻烦.

I'm trying to improve the performance of our application. We have a lot of Activator.CreateInstance calls that are causing some grief.

我们基于一个接口(ITabDocument)实例化了很多类,环顾四周后,我想到了使用这段代码:

We instantiate a lot of classes based on an interface (ITabDocument) and after looking around I thought of using this code:

代码并不比使用我们拥有的 Activator.CreateInstance 代码更好(实际上稍微慢一点).

The code is no better (infact marginally slower) than using the Activator.CreateInstance code we had.

    public static Func<T> CreateInstance<T>(Type objType) where T : class, new()
    {
        var dynMethod = new DynamicMethod("DM$OBJ_FACTORY_" + objType.Name, objType, null, objType);
        ILGenerator ilGen = dynMethod.GetILGenerator();
        ilGen.Emit(OpCodes.Newobj, objType.GetConstructor(Type.EmptyTypes));
        ilGen.Emit(OpCodes.Ret);
        return (Func<T>)dynMethod.CreateDelegate(typeof(Func<T>));
    }

我想知道为什么会这样,我所做的就是:

I'm wondering why this is, all I'm doing is:

ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));

有没有更好的方法来创建有助于上述的对象?当您不确定具体类型时,它有点困难.

Is there a better way of creating objects which would assist with the above? Its a little hard when you're not sure of the concrete type.

推荐答案

我在这些之间做了一些基准测试(我会写下最基本的细节):

I did some benchmarking between these (I would write down the bare minimum details):

public static T Instance() //~1800 ms
{
    return new T();
}

public static T Instance() //~1800 ms
{
    return new Activator.CreateInstance<T>();
}

public static readonly Func<T> Instance = () => new T(); //~1800 ms

public static readonly Func<T> Instance = () => 
                                 Activator.CreateInstance<T>(); //~1800 ms

//works for types with no default constructor as well
public static readonly Func<T> Instance = () => 
               (T)FormatterServices.GetUninitializedObject(typeof(T)); //~2000 ms


public static readonly Func<T> Instance = 
     Expression.Lambda<Func<T>>(Expression.New(typeof(T))).Compile();  
     //~50 ms for classes and ~100 ms for structs

正如 CD 所说,编译表达式是最快的,而且优势很大.除 (T)FormatterServices.GetUninitializedObject(typeof(T)) 之外的所有方法 仅适用于具有默认构造函数的类型.

As CD says compiled expression is the fastest, and by a big margin. All the methods except (T)FormatterServices.GetUninitializedObject(typeof(T)) work only for types with default constructor.

当每个泛型类型都有一个静态类时,缓存编译的结果委托是微不足道的.喜欢:

And caching the compiled resultant delegate is trivial when you have a static class per generic type. Like:

public static class New<T> where T : new()
{
    public static readonly Func<T> Instance = Expression.Lambda<Func<T>>
                                              (
                                               Expression.New(typeof(T))
                                              ).Compile();
}

注意 new 约束.随便打电话

Note the new constraint. Call anything

MyType me = New<MyType>.Instance();

除了第一次将类加载到内存中之外,执行速度将是最快的.

Except for the first time the class is being loaded in memory, the execution is going to be fastest.

为了有一个可以处理带有和不带有默认构造函数的类型的类,我采用了一种混合方法,从这里:

To have a class that handles both types with default constructor and without, I took a hybrid approach, from here:

public static class New<T>
{
    public static readonly Func<T> Instance = Creator();

    static Func<T> Creator()
    {
        Type t = typeof(T);
        if (t == typeof(string))
            return Expression.Lambda<Func<T>>(Expression.Constant(string.Empty)).Compile();

        if (t.HasDefaultConstructor())
            return Expression.Lambda<Func<T>>(Expression.New(t)).Compile();

        return () => (T)FormatterServices.GetUninitializedObject(t);
    }
}

public static bool HasDefaultConstructor(this Type t)
{
    return t.IsValueType || t.GetConstructor(Type.EmptyTypes) != null;
}

也会以有效的方式处理值类型.

Will handle value types too in an efficient manner.

请注意,(T)FormatterServices.GetUninitializedObject(t) 对于 string 将失败.因此,对字符串进行了特殊处理以返回空字符串.

Note that (T)FormatterServices.GetUninitializedObject(t) will fail for string. Hence special handling for string is in place to return empty string.

这篇关于快速创建对象而不是 Activator.CreateInstance(type)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆