我创建了一个简单的C#
程序:
class Program
{
static void Main(string[] args)
{
Int32? a = null;
object x = a;
}
}
根据MSDN:
如果对象非空,则基于可空类型的对象仅加框。如果HasValue为false,则将对象引用分配为null 而不是装箱。
我已在ILDASM
中尝试了我的可执行文件,并发现IL
代码已调用 box 方法。
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 17 (0x11)
.maxstack 1
.locals init ([0] valuetype [mscorlib]System.Nullable`1<int32> a,
[1] object x)
IL_0000: nop
IL_0001: ldloca.s a
IL_0003: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0009: ldloc.0
IL_000a: box valuetype [mscorlib]System.Nullable`1<int32>
IL_000f: stloc.1
IL_0010: ret
} // end of method Program::Main
我的问题是:为什么叫它? 也许我做错了什么或误解了什么?
答案 0 :(得分:6)
设置值的尝试并不意味着它实际上是一个盒装值 - <div ng-app="customInterpolationApp" ng-controller="DemoController as demo">
//demo.label//
</div>
将是x
,而不是盒装null
。我认为MSDN正试图解释:
null
可是:
Int32? a = null;
object x = a;
object y = a;
object.ReferenceEquals(x, y); // true
至于在发布模式下进行编译 - 可能不会尝试将值设置为值,因为在编译时已知Int32? a = 3;
object x = a;
object y = a;
object.ReferenceEquals(x, y); // false
为a
- 如果{{1} }是一个公共方法的参数,它可能总是试图打包该值(但实际上从来没有框null
)。
答案 1 :(得分:3)
您正在调试模式下编译代码。将其更改为Release,您将获得所需的行为。在这种情况下,它将一起省略所有的分配:
.method private hidebysig static
void Main (string[] args
) cil managed
{
// Method begins at RVA 0x2054
// Code size 11 (0xb)
.maxstack 1
.locals init (
[0] valuetype [mscorlib]System.Nullable`1<int32>
)
IL_0000: ldloca.s 0
IL_0002: initobj valuetype [mscorlib]System.Nullable`1<int32>
IL_0008: ldloc.0
IL_0009: pop
IL_000a: ret
} // end of method C::Main
如果稍微更改代码并尝试接受Int?
作为方法的参数,并在编译时显式传递null
,则发布模式下的编译器将发出{{1指令。
假设:
box
你会看到:
public void M(int? x)
{
object y = x;
Console.WriteLine(y);
}
public void Main()
{
M(null);
}