我正在努力提高我们应用程序的性能。我们有很多 Activator.CreateInstance 调用导致了一些问题。
我们基于接口(interface) (ITabDocument) 实例化了很多类,环顾四周后我想到了使用以下代码:
该代码并不比使用我们已有的 Activator.CreateInstance 代码好(实际上稍微慢一点)。
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>));
}
我想知道这是为什么,我所做的就是:
ITabDocument document = CreateInstance<ITabDocument>(Type.GetType("[Company].Something"));
是否有更好的创建对象的方法来帮助完成上述任务?当您不确定具体类型时,这有点困难。
最佳答案
我在这些之间做了一些基准测试(我会写下最低限度的细节):
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))
之外的所有方法 仅适用于具有默认构造函数的类型。
当每个泛型都有一个静态类时,缓存编译后的结果委托(delegate)是微不足道的。喜欢:
public static class New<T> where T : new()
{
public static readonly Func<T> Instance = Expression.Lambda<Func<T>>
(
Expression.New(typeof(T))
).Compile();
}
请注意新
约束。随叫随到
MyType me = New<MyType>.Instance();
除了第一次将类加载到内存中外,执行速度最快。
为了拥有一个可以处理带默认构造函数和不带默认构造函数的两种类型的类,我采用了混合方法,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;
}
也将以高效的方式处理值类型。
请注意 (T)FormatterServices.GetUninitializedObject(t)
对于 string
将失败。因此,对字符串进行特殊处理以返回空字符串。
关于c# - 快速创建对象而不是 Activator.CreateInstance(type),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6582259/