Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/293.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 给定;其中T:new();,是不是;新的T();是否在内部使用Activator.CreateInstance?_C#_Generics_Reflection_Activator_Type Constraints - Fatal编程技术网

C# 给定;其中T:new();,是不是;新的T();是否在内部使用Activator.CreateInstance?

C# 给定;其中T:new();,是不是;新的T();是否在内部使用Activator.CreateInstance?,c#,generics,reflection,activator,type-constraints,C#,Generics,Reflection,Activator,Type Constraints,如果我有一个类型参数约束new(): void Foo(),其中T:new() { var t=新的t(); } new T()是否会在内部使用Activator.CreateInstance方法(即反射)?是。它对引用类型有效 在以下版本编译代码上使用ILSpy: public static void DoWork<T>() where T: new() { T t = new T(); Console.WriteLine(t.To

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

void Foo(),其中T:new()
{
var t=新的t();
}

new T()
是否会在内部使用
Activator.CreateInstance
方法(即反射)?

是。它对引用类型有效

在以下版本编译代码上使用ILSpy:

    public static void DoWork<T>() where T: new()
    {
        T t = new T();
        Console.WriteLine(t.ToString());
    }
publicstaticvoiddowork(),其中T:new()
{
T=新的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<!!T>()

    IL_0020: stloc.0
    IL_0021: ldloca.s t
    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
.method公共隐藏
实例void DoWork()cil托管
{
//方法从RVA 0x2064开始
//代码大小52(0x34)
.maxstack 2
.init(
[0]!!T T,
[1] !!T CS$0$0000,
[2] !!T CS$0$0001
)
IL_0000:ldloca.s$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.s t
IL_0023:受约束。!!T
IL_0029:callvirt实例字符串[mscorlib]System.Object::ToString()
IL_002e:调用void[mscorlib]System.Console::WriteLine(字符串)
IL_0033:ret
}//方法结束程序::DoWork
或者在C#中:

public void DoWork(),其中T:new()
{
T=(默认值(T)=null)?Activator.CreateInstance():默认值(T);
Console.WriteLine(t.ToString());
}

JIT将为传入的每个不同的值类型参数创建不同的编译指令,但对引用类型使用相同的指令——因此Activator.CreateInstance()是的,这是正确的编辑2:这里有一个很好的解释,说明了如何以及为什么

为了验证,我编译了以下方法:

public static T Create<T>() where T: new() {
    return new T();
}
publicstatict Create(),其中T: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<!!T>()
    L_001f: ret 
}
.method公共隐藏静态!!T Create()cil管理
{
.maxstack 2
.init(
[0]!!T本地,
[1] !!T local2)
L_0000:ldloca.s本地
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<!!T>()
    L_0021: stloc.0 
    L_0022: br.s L_0024
    L_0024: ldloc.0 
    L_0025: ret 
}
.method公共隐藏静态!!T Create()cil管理
{
.maxstack 2
.init(
[0]!!T CS$1$0000,
[1] !!T CS$0$0001)
L_0000:没有
L_0001:ldloca.s CS$0$0001
L_0003:initobj!!T
L_0009:ldloc.1
L_000a:盒子!!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
}

对于值类型,它不使用activator,只返回
默认(t)
值,否则它调用
activator.CreateInstance
方法。

@Oded如果您试图更好地理解正在编程的环境,那么是的-这很重要!:-)@克拉根:伊尔达斯姆,monodis@seheIL Spy是我目前选择的反编译器-我参与并反编译Microsoft程序集(尝试回答类似问题)的时候实际上非常有启发性,并对我的编码风格产生了相当大的影响。请注意,随着Roslyn的出现,这种行为发生了变化。如果添加了
struct
约束,则先前未调用
Activator.CreateInstance
。今天,不管约束如何,IL都将调用
Activator.CreateInstance
。非常相似的q:@Jason:
initobj
被定义为“将指定地址处值类型的每个字段初始化为空引用或相应基元类型的0。。。与Newobj不同,initobj不调用构造函数方法。Initobj用于初始化值类型,而newobj用于分配和初始化对象。“没有迹象表明它调用引用类型的默认构造函数。我假设它相当于
default(T)
@CodeInChaos:我已经删除了我的评论。我犯了一个错误。好吧,那么最大的问题是为什么。为什么编译器不发出一条
newobj
指令?那么如果约束是
类,new()
?它仍然使用激活器-我假设是因为
newobj
的预期标记是构造函数标记,而不是类型标记。对于“值类型”也是如此。
请参阅本书第544页/第11章-C#编程语言-第三版
.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<!!T>()
    L_001f: ret 
}
.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<!!T>()
    L_0021: stloc.0 
    L_0022: br.s L_0024
    L_0024: ldloc.0 
    L_0025: ret 
}