C#空传播 - 哪里魔术发生? [英] C# Null propagation - Where does the magic happen?
问题描述
空的传播是一个很不错的功能 - 但 ,其中的和 如何的不实际的魔术发生?
哪里 FRM .Close()
如果(FRM!= NULL)得到改变,以 frm.Close();
- 它实际上得到改变那种代码在所有
Null propagation is a very nice feature - but where and how does the actual magic happen?
Where does frm?.Close()
get changed to if(frm != null) frm.Close();
- Does it actually get changed to that kind of code at all?
推荐答案
这是由编译器完成?它不会改变 FRM .Close()
到如果(FRM!= NULL)frm.Close();
在重新编写源代码的条款,但它的确实的发射IL字节码检查空
It is done by the compiler. It doesn't change frm?.Close()
to if(frm != null) frm.Close();
in terms of re-writing the source code, but it does emit IL bytecode which checks for null.
看看下面的例子:
void Main()
{
Person p = GetPerson();
p?.DoIt();
}
编译为:
Compiles to:
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
这可以解读为:
呼叫
- 呼叫 GetPerson( )
- 存储在堆栈上的结果结果
DUP
- 推值压入调用堆栈(再次)
brtrue.s
- 弹出堆栈顶部的值。如果这是真的,还是不空(引用类型),然后跳转到 IL_000B
call
- Call GetPerson()
- store the result on the stack.
dup
- Push the value onto the call stack (again)
brtrue.s
- Pop the top value of the stack. If it is true, or not-null (reference type), then branch to IL_000B
如果结果是假的(也就是说,对象是的空的)结果
弹出
- 弹出堆栈(清除栈,我们没有不再需要人
)结果
RET
的值 - 返回
If the result is false (that is, the object is null)
pop
- Pops the stack (clear out the stack, we no longer need the value of Person
)
ret
- Returns
如果值是true(也就是说,对象是的不为空的)结果
呼叫
- 呼叫 DOIT()
在堆栈的最顶部的值(目前的结果 GetPerson
)< BR>
RET
- 返回
If the value is true (that is, the object is not null)
call
- Call DoIt()
on the top-most value of the stack (currently the result of GetPerson
).
ret
- Returns
手动空检查:
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
请注意,上面是的不的一样?
,但是。检查的有效结果是相同的。
Note that the above is not the same as ?.
, however the effective outcome of the check is the same.
没有空检查:
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
这篇关于C#空传播 - 哪里魔术发生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!