Dav*_*don 6 c# null propagation
空传播是一个非常好的功能 - 但实际魔法在哪里以及如何发生?哪里frm?.Close()得到改变if(frm != null) frm.Close();-它是否真正得到改变那种代码呢?
Rob*_*Rob 20
它由编译器完成.它不改变frm?.Close()到if(frm != null) frm.Close();在重新编写源代码方面,但它不发射IL字节码检查空.
请看以下示例:
void Main()
{
Person p = GetPerson();
p?.DoIt();
}
Run Code Online (Sandbox Code Playgroud)
编译为:
IL_0000: ldarg.0
IL_0001: call UserQuery.GetPerson
IL_0006: dup
IL_0007: brtrue.s IL_000B
IL_0009: pop
IL_000A: ret
IL_000B: call UserQuery+Person.DoIt
IL_0010: ret
Run Code Online (Sandbox Code Playgroud)
这可以理解为:
call- 调用GetPerson()- 将结果存储在堆栈中.
dup- 将值推入调用堆栈(再次)
brtrue.s- 弹出堆栈的最高值.如果为true,或者为null(引用类型),则转到IL_000B
如果结果为false(即对象为null)
pop- 弹出堆栈(清除堆栈,我们不再需要值Person)
ret- 返回
如果值为true(即,对象不为null)
call- 调用DoIt()堆栈的最顶层值(当前是结果GetPerson).
ret - 退货
手动空检查:
Person p = GetPerson();
if (p != null)
p.DoIt();
IL_0000: ldarg.0
IL_0001: call UserQuery.GetPerson
IL_0006: stloc.0 // p
IL_0007: ldloc.0 // p
IL_0008: brfalse.s IL_0010
IL_000A: ldloc.0 // p
IL_000B: callvirt UserQuery+Person.DoIt
IL_0010: ret
Run Code Online (Sandbox Code Playgroud)
请注意,上述内容并不相同?.,但检查的有效结果是相同的.
没有空检查:
void Main()
{
Person p = GetPerson();
p.DoIt();
}
IL_0000: ldarg.0
IL_0001: call UserQuery.GetPerson
IL_0006: callvirt UserQuery+Person.DoIt
IL_000B: ret
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
379 次 |
| 最近记录: |