Null-Condition 运算符是否在连续使用站点中进行了优化,还是会导致重复检查
本文关键字:优化 检查 连续 是否 运算符 站点 Null-Condition | 更新日期: 2023-09-27 18:31:38
使用 null 条件运算符会重复 null 检查吗? 例如
var x = instance?.Property1;
var y = instance?.Property2;
这是否被编译成这样:
if (instance != null)
{
var x = instance.Property1;
var y = instance.Property2;
}
还是这个?
if (instance != null)
{
var x = instance.Property1;
}
if (instance != null)
{
var y = instance.Property2;
}
如果是前者,如果两行之间有其他代码,会有什么区别吗? 换句话说,编译器/优化器有多聪明?
编译器似乎对此一无所知。
代码:
var x = instance?.Property1;
var y = instance?.Property2;
。编译为非优化:
IL_0000: nop
IL_0001: newobj UserQuery+Class..ctor
IL_0006: stloc.0 // instance
IL_0007: ldloc.0 // instance
IL_0008: brtrue.s IL_000D
IL_000A: ldnull
IL_000B: br.s IL_0013
IL_000D: ldloc.0 // instance
IL_000E: ldfld UserQuery+Class.Property1
IL_0013: stloc.1 // x
IL_0014: ldloc.0 // instance
IL_0015: brtrue.s IL_001A
IL_0017: ldnull
IL_0018: br.s IL_0020
IL_001A: ldloc.0 // instance
IL_001B: ldfld UserQuery+Class.Property2
IL_0020: stloc.2 // y
IL_0021: ret
Class..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: nop
IL_0007: ret
。并优化为:
IL_0000: newobj UserQuery+Class..ctor
IL_0005: dup
IL_0006: dup
IL_0007: brtrue.s IL_000C
IL_0009: pop
IL_000A: br.s IL_0012
IL_000C: ldfld UserQuery+Class.Property1
IL_0011: pop
IL_0012: dup
IL_0013: brtrue.s IL_0017
IL_0015: pop
IL_0016: ret
IL_0017: ldfld UserQuery+Class.Property2
IL_001C: pop
IL_001D: ret
Class..ctor:
IL_0000: ldarg.0
IL_0001: call System.Object..ctor
IL_0006: ret
两者都清楚地有两个分支检查。
它执行两个单独的 If.。否则,在您的情况下使用 null 条件运算符检查赋值。下面是一个反汇编的示例代码
源代码:
public class nulltest
{
public void test()
{
var instance = new testclass();
var x = instance?.prop1;
var y = instance?.prop2;
}
}
public class testclass
{
public int prop1;
public int prop2;
}
反汇编代码 (ILSpy):
public class nulltest
{
public void test()
{
testclass testclass = new testclass();
if (testclass == null)
{
int? arg_20_0 = null;
}
else
{
new int?(testclass.prop1);
}
if (testclass == null)
{
int? arg_3A_0 = null;
}
else
{
new int?(testclass.prop2);
}
}
}
我使用int
作为属性的类型,但上述情况应该适用于任何其他情况。
编译器很严谨,想想这段代码。
class Tricky
{
public int Property1
{
get
{
Program.instance = null;
return 1;
}
}
public int Property2
{
get
{
return 2;
}
}
}
class Program
{
public static Tricky instance = new Tricky();
public static void Main(string[] arg)
{
var x = instance?.Property1;
var y = instance?.Property2;
//what do you think the values of x,y
}
}
预期结果为:x == 1, y is null
。但是,如果编译器使用一个 if
语句优化代码,则会抛出NullReferenceException
。这意味着,使用一个if
语句,不是一个聪明的优化,它不是一个优化,因为它是错误的。