Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/335.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# IL中调用实例与newobj实例之间的差异_C#_Il - Fatal编程技术网

C# IL中调用实例与newobj实例之间的差异

C# IL中调用实例与newobj实例之间的差异,c#,il,C#,Il,我正在深入研究C#,并使用可空值类型。出于实验目的,我写了一段代码: private static void HowNullableWorks() { int test = 3; int? implicitConversion = test; Nullable<int> test2 = new Nullable<int>(3); MethodThatTakesNullableInt(null

我正在深入研究C#,并使用可空值类型。出于实验目的,我写了一段代码:

    private static void HowNullableWorks()
    {
        int test = 3;
        int? implicitConversion = test;
        Nullable<int> test2 = new Nullable<int>(3);

        MethodThatTakesNullableInt(null);
        MethodThatTakesNullableInt(39);
    }
private static void HowNullableWorks()
{
int检验=3;
int?隐式转换=测试;
Nullable test2=新的Nullable(3);
方法获取空值(null);
方法:采用随机分组法(39例);
}
我很高兴看到implicitConversion/test2变量初始化为:

call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
调用实例void valuetype[mscorlib]System.Nullable`1::.ctor(!0)
指令,而当调用采用LLABLEINT的方法时,我可以看到:

IL_0017:  initobj    valuetype [mscorlib]System.Nullable`1<int32>
IL_0017:initobj值类型[mscorlib]系统。可为null`1

IL_0026:newobj实例void valuetype[mscorlib]System.Nullable`1::.ctor(!0)
我明白。我想我也会看到隐式转换的newobj指令

这是完整的IL代码:

.method private hidebysig static void  HowNullableWorks() cil managed
{
  // Code size       50 (0x32)
  .maxstack  2
  .locals init ([0] int32 test,
           [1] valuetype [mscorlib]System.Nullable`1<int32> implicitConversion,
           [2] valuetype [mscorlib]System.Nullable`1<int32> test2,
           [3] valuetype [mscorlib]System.Nullable`1<int32> CS$0$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.3
  IL_0002:  stloc.0
  IL_0003:  ldloca.s   implicitConversion
  IL_0005:  ldloc.0
  IL_0006:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_000b:  nop
  IL_000c:  ldloca.s   test2
  IL_000e:  ldc.i4.3
  IL_000f:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_0014:  nop
  IL_0015:  ldloca.s   CS$0$0000
  IL_0017:  initobj    valuetype [mscorlib]System.Nullable`1<int32>
  IL_001d:  ldloc.3
  IL_001e:  call       void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype [mscorlib]System.Nullable`1<int32>)
  IL_0023:  nop
  IL_0024:  ldc.i4.s   39
  IL_0026:  newobj     instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_002b:  call       void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype [mscorlib]System.Nullable`1<int32>)
  IL_0030:  nop
  IL_0031:  ret
} // end of method Program::HowNullableWorks
.method private hidebysing static void HowNullableWorks()cil managed
{
//代码大小50(0x32)
.maxstack 2
.init([0]int32测试,
[1] valuetype[mscorlib]系统。可为null的`1隐式转换,
[2] valuetype[mscorlib]系统。可为null的'1 test2,
[3] valuetype[mscorlib]系统。可为空'1 CS$0$0000)
IL_0000:没有
IL_0001:ldc.i4.3
IL_0002:stloc.0
IL_0003:ldloca.s隐式转换
IL_0005:ldloc.0
IL_0006:调用实例void valuetype[mscorlib]System.Nullable`1::.ctor(!0)
没有
IL_000c:ldloca.s测试2
IL_000e:ldc.i4.3
IL_000f:调用实例void valuetype[mscorlib]System.Nullable`1::.ctor(!0)
IL_0014:没有
IL_0015:ldloca.s CS$0$0000
IL_0017:initobj valuetype[mscorlib]系统。可为null`1
IL_001d:ldloc.3
IL_001e:调用void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype[mscorlib]System.Nullable`1)
伊卢0023:没有
IL_0024:ldc.i4.s 39
IL_0026:newobj实例void valuetype[mscorlib]System.Nullable`1::.ctor(!0)
IL_002b:调用void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype[mscorlib]System.Nullable`1)
IL_0030:没有
IL_0031:ret
}//方法结束程序::HowNullableWorks

首先,它看起来像是在调试模式下编译的(基于
nop
s)-如果在发布模式下编译,可能会看到不同的代码发出

ECMA CLR规范(初始化值类型实例)第I.12.1.6.2.1节规定:

初始化值类型的主目录有三个选项 例如。您可以通过加载家庭地址将其归零(请参见 表I.8:原籍地址和类型)和使用
initobj
指令(对于局部变量,也可通过设置 方法头中的
localsinit
位)。你可以打个电话 通过加载家庭地址的用户定义构造函数(参见表 I.8:家庭地址和类型),然后致电 直接调用构造函数。或者,您可以将现有实例复制到 家庭,如§I.12.1.6.2.2所述

代码中可空类型的前三次使用导致以局部变量存储空值,因此此注释是相关的(局部变量是值的一种类型):前两次是您声明的局部变量
implicitConversion
test
,第三个是编译器生成的名为
CS$0$0000
的临时文件。正如ECMA规范所指出的,可以通过使用
initobj
(相当于结构的默认无参数构造函数,在这种情况下用于
CS$0$0000
)或通过加载本地地址并调用构造函数(用于其他两个本地值)来初始化这些本地值

但是,对于最后一个可为null的实例(由
39
的隐式转换创建),结果不会存储在本地文件中,而是在堆栈上生成的,因此初始化主文件的规则在此不适用。相反,编译器只使用
newobj
在堆栈上创建值(与任何值或引用类型一样)

您可能想知道为什么编译器为调用
MethodThatTakesNullableInt(null)
而不是为调用
MethodThatTakesNullableInt(39)
生成一个本地函数。我怀疑答案是编译器总是使用
initobj
调用默认构造函数(然后需要值的本地或其他home),但在还没有合适的home时,使用
newobj
调用其他构造函数并将结果存储在堆栈上

有关更多信息,请参见规范第III.4.21节(新OBJ)中的注释:

通常不会使用
newobj
创建值类型。他们通常是 使用
newarr
(用于 零基一维数组),或作为对象的字段。一旦 分配后,使用
initobj
初始化它们。但是,
newobj
指令可用于在上创建值类型的新实例 然后可以作为参数传递的堆栈,存储在本地, 等等

.method private hidebysig static void  HowNullableWorks() cil managed
{
  // Code size       50 (0x32)
  .maxstack  2
  .locals init ([0] int32 test,
           [1] valuetype [mscorlib]System.Nullable`1<int32> implicitConversion,
           [2] valuetype [mscorlib]System.Nullable`1<int32> test2,
           [3] valuetype [mscorlib]System.Nullable`1<int32> CS$0$0000)
  IL_0000:  nop
  IL_0001:  ldc.i4.3
  IL_0002:  stloc.0
  IL_0003:  ldloca.s   implicitConversion
  IL_0005:  ldloc.0
  IL_0006:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_000b:  nop
  IL_000c:  ldloca.s   test2
  IL_000e:  ldc.i4.3
  IL_000f:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_0014:  nop
  IL_0015:  ldloca.s   CS$0$0000
  IL_0017:  initobj    valuetype [mscorlib]System.Nullable`1<int32>
  IL_001d:  ldloc.3
  IL_001e:  call       void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype [mscorlib]System.Nullable`1<int32>)
  IL_0023:  nop
  IL_0024:  ldc.i4.s   39
  IL_0026:  newobj     instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_002b:  call       void csharp.in.depth._2nd.Program::MethodThatTakesNullableInt(valuetype [mscorlib]System.Nullable`1<int32>)
  IL_0030:  nop
  IL_0031:  ret
} // end of method Program::HowNullableWorks