【发布时间】:2015-12-30 18:24:02
【问题描述】:
鉴于这两种方法:
static void M1(Person p)
{
if (p != null)
{
var p1 = p.Name;
}
}
static void M2(Person p)
{
var p1 = p?.Name;
}
为什么 M1 IL 代码使用callvirt:
IL_0007: brfalse.s IL_0012
IL_0009: nop
IL_000a: ldarg.0
IL_000b: callvirt instance string ConsoleApplication4.Person::get_Name()
而 M2 IL 使用 call:
brtrue.s IL_0007
IL_0004: ldnull
IL_0005: br.s IL_000d
IL_0007: ldarg.0
IL_0008: call instance string ConsoleApplication4.Person::get_Name()
我只能猜到它,因为在 M2 中我们知道 p 不是 null 之类的
new MyClass().MyMethod();
是真的吗?
如果是,如果p在其他线程中为空怎么办?
【问题讨论】:
-
最好能展示一个实际的虚拟成员在被覆盖时是如何被调用的。特别是在
?.面前。当被覆盖的成员是sealed并被专门调用时,会有什么行为?如果还是callvirt,可能是Roslyn的优化机会:) -
@leppie C# 为此生成
callvirt。但我不知道运行时会发生什么。