如果您有以下代码:
static T GenericConstruct() where T : new() { return new T(); }
C#编译器坚持发出对Activator.CreateInstance的调用,这比本机构造函数慢得多.
我有以下解决方法:
public static class ParameterlessConstructorwhere T : new() { public static T Create() { return _func(); } private static Func CreateFunc() { return Expression.Lambda >( Expression.New( typeof( T ) ) ).Compile(); } private static Func _func = CreateFunc(); } // Example: // Foo foo = ParameterlessConstructor .Create();
但是,为什么这个解决方案应该是必要的,这对我没有意义.
我怀疑这是一个JITting问题.目前,JIT为所有引用类型参数重用相同的生成代码 - 因此一个List
vtable指向与之相同的机器代码List
.如果new T()
必须在JITted代码中解析每个调用,那将无效.
只是一个猜测,但它有一定的意义.
一个有趣的小点:在任何情况下都不会调用值类型的无参数构造函数(如果有的话)(这种情况很少见).有关详细信息,请参阅我最近的博文 我不知道是否有任何方法可以强制它在表达式树中.
这很可能是因为不清楚T是值类型还是引用类型.在非通用场景中创建这两种类型会产生非常不同的IL.面对这种模糊性,C#被迫使用通用的类型创建方法.Activator.CreateInstance符合要求.
快速实验似乎支持这一想法.如果键入以下代码并检查IL,它将使用initobj而不是CreateInstance,因为类型没有歧义.
static void Create() where T : struct { var x = new T(); Console.WriteLine(x.ToString()); }
将其切换为类和new()约束仍会强制激活Activator.CreateInstance.