快速创建对象而不是 Activator.CreateInstance(type) [英] Fast creation of objects instead of 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屋!