编程语言
首页 > 编程语言> > C#Null条件运算符替代(条件赋值)?

C#Null条件运算符替代(条件赋值)?

作者:互联网

C# null-conditional operator允许有用的短路:

double? range = (unit as RangedUnit)?.WeaponRange;

遗憾的是,无条件运算符不能以相同的方式用于短手赋值,因为它返回一个值(不能在左手赋值中使用):

(unit as RangedUnit)?.PreferredTarget = UnitType.Melee;

导致可能的替代语法:

if (unit is RangedUnit)
{
    (unit as RangedUnit).PreferredTarget = UnitType.Melee;
}

如果编译器知道RangedUnit是引用类型(不是值类型),为什么它不能有条件地执行简写语法

refTypeInstance?.SomeField = value;

(即如果refTypeInstance为null,则根本不执行任何操作.如果refTypeInstance不为null,则执行语句)

更新(结论):

>无法在赋值语句的左侧使用空条件运算符,因为这会违反赋值语句的表达式树的预期求值逻辑(短路赋值操作而根本不执行它)
>理想的解决方案是一个新的条件赋值运算符(仅当赋值的左侧不为空时才执行),实质上是’如果不是空的一个赋值一个衬里’

解决方法:

您期望的行为:

(i.e. If refTypeInstance is null, then simply do nothing. If refTypeInstance is not null, then execute the statement)

由于运算符的工作方式,这是不可能的.更具体地说,您遇到运算符优先级问题以及表达式树是如何形成的:

在声明中

(unit as RangeUnit).PreferredTarget = UnitType.Melee;

赋值运算符(=)将位于表达式树的根中,左侧和右侧表达式为分支.

评估左手时(在分配之前)会发生NullReferenceException.此时编译器已经开始评估=.由于解引用运算符(.)将在运行时抛出NullReferenceException,因此编译器可以安全地继续解析表达式树.

另一方面,如果允许这样的陈述:

(unit as RangeUnit)?.PreferredTarget = UnitType.Melee;

…编译器必须发出代码来检查refTypeInstance的值是否为null.它可以做到这一点,但问题是,编译器对目前正在经历的表达式树做了什么?它不能像第一个例子那样简单地继续下去,因为它必须丢弃表达式树和表达式.在树下.它基本上必须插入两个解析树的替代方案,一个在左边?如果不是,则为null.然而,这将改变控制流程,这绝对不是您对运算符的期望.

或者换句话说:只要?只是将运算符的评估短路到表达式树的分支,你会认为这是一种预期的行为.但在这种情况下,这会改变表达式树中较高的运算符的行为,这是您绝对不会期望的.

标签:c,short-circuiting,null-conditional-operator
来源: https://codeday.me/bug/20190608/1198348.html