为什么在使用具有 new() 约束的泛型类型调用 new 时,c# 编译器会发出 Activator.CreateInstance? [英] Why does the c# compiler emit Activator.CreateInstance when calling new in with a generic type with a new() constraint?
问题描述
当您有如下代码时:
static T GenericConstruct<T>() where T : new()
{
return new T();
}
C# 编译器坚持发出对 Activator.CreateInstance 的调用,这比本地构造函数慢得多.
The C# compiler insists on emitting a call to Activator.CreateInstance, which is considerably slower than a native constructor.
我有以下解决方法:
public static class ParameterlessConstructor<T>
where T : new()
{
public static T Create()
{
return _func();
}
private static Func<T> CreateFunc()
{
return Expression.Lambda<Func<T>>( Expression.New( typeof( T ) ) ).Compile();
}
private static Func<T> _func = CreateFunc();
}
// Example:
// Foo foo = ParameterlessConstructor<Foo>.Create();
但我不明白为什么需要这种解决方法.
But it doesn't make sense to me why this workaround should be necessary.
推荐答案
我怀疑这是一个 JITting 问题.目前,JIT 为所有引用类型参数重用相同的生成代码 - 因此 List
的 vtable 指向与 List
.如果每个 new T()
调用都必须在 JIT 代码中解析,那这将行不通.
I suspect it's a JITting problem. Currently, the JIT reuses the same generated code for all reference type arguments - so a List<string>
's vtable points to the same machine code as that of List<Stream>
. That wouldn't work if each new T()
call had to be resolved in the JITted code.
只是一个猜测,但它一定有一定的意义.
Just a guess, but it makes a certain amount of sense.
一个有趣的小点:在两种情况下都不会调用值类型的无参数构造函数,如果有的话(这种情况非常罕见).请参阅我最近的博文详情.不知道有没有什么方法可以强制到表达式树中.
One interesting little point: in neither case does the parameterless constructor of a value type get called, if there is one (which is vanishingly rare). See my recent blog post for details. I don't know whether there's any way of forcing it in expression trees.
这篇关于为什么在使用具有 new() 约束的泛型类型调用 new 时,c# 编译器会发出 Activator.CreateInstance?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!