给定“where T:new()”,“new T()”在内部使用Activator.CreateInstance吗?

如果我有一个类型参数约束new()

 void Foo() where T : new() { var t = new T(); } 

new T()会在内部使用Activator.CreateInstance方法(即reflection)吗?

是的,这是真的。 编辑2:这是一个很好的解释如何以及为什么。

http://www.simple-talk.com/community/blogs/simonc/archive/2010/11/17/95700.aspx

为了validation,我编译了以下方法:

 public static T Create() where T: new() { return new T(); } 

这是使用.NET 3.5 SP1中的C#编译器编译时生成的IL:

 .method public hidebysig static !!T Create<.ctor T>() cil managed { .maxstack 2 .locals init ( [0] !!T local, [1] !!T local2) L_0000: ldloca.s local L_0002: initobj !!T L_0008: ldloc.0 L_0009: box !!T L_000e: brfalse.s L_001a L_0010: ldloca.s local2 L_0012: initobj !!T L_0018: ldloc.1 L_0019: ret L_001a: call !!0 [mscorlib]System.Activator::CreateInstance() L_001f: ret } 

编辑: C#4编译器创建略有不同但相似的代码:

 .method public hidebysig static !!T Create<.ctor T>() cil managed { .maxstack 2 .locals init ( [0] !!T CS$1$0000, [1] !!T CS$0$0001) L_0000: nop L_0001: ldloca.s CS$0$0001 L_0003: initobj !!T L_0009: ldloc.1 L_000a: box !!T L_000f: brfalse.s L_001c L_0011: ldloca.s CS$0$0001 L_0013: initobj !!T L_0019: ldloc.1 L_001a: br.s L_0021 L_001c: call !!0 [mscorlib]System.Activator::CreateInstance() L_0021: stloc.0 L_0022: br.s L_0024 L_0024: ldloc.0 L_0025: ret } 

在值类型的情况下,它不使用激活器,而只返回default(T)值,否则它将调用Activator.CreateInstance方法。

是。 它适用于参考类型。

在以下发布编译的代码上使用ILSpy:

  public static void DoWork() where T: new() { T t = new T(); Console.WriteLine(t.ToString()); } 

墓内

 .method public hidebysig instance void DoWork<.ctor T> () cil managed { // Method begins at RVA 0x2064 // Code size 52 (0x34) .maxstack 2 .locals init ( [0] !!T t, [1] !!T CS$0$0000, [2] !!T CS$0$0001 ) IL_0000: ldloca.s CS$0$0000 IL_0002: initobj !!T IL_0008: ldloc.1 IL_0009: box !!T IL_000e: brfalse.s IL_001b IL_0010: ldloca.s CS$0$0001 IL_0012: initobj !!T IL_0018: ldloc.2 IL_0019: br.s IL_0020 IL_001b: call !!0 [mscorlib]System.Activator::CreateInstance() IL_0020: stloc.0 IL_0021: ldloca.st IL_0023: constrained. !!T IL_0029: callvirt instance string [mscorlib]System.Object::ToString() IL_002e: call void [mscorlib]System.Console::WriteLine(string) IL_0033: ret } // end of method Program::DoWork 

或者在C#中:

 public void DoWork() where T : new() { T t = (default(T) == null) ? Activator.CreateInstance() : default(T); Console.WriteLine(t.ToString()); } 

JIT将为传入的每个不同的值类型参数创建不同的编译指令,但将对引用类型使用相同的指令 – 因此Activator.CreateInstance()