C#空条件运算符替代(有条件赋值)?
C#空条件运算符允许有用的短路:
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,则执行该语句)
更新(结论):
您期待的行为:
(即,如果refTypeInstance为null,则不做任何事情。如果refTypeInstance不为null,则执行该语句)
由于操作员的工作方式,这是不可能的。 更具体地说,您在运算符优先级方面存在问题,以及如何基于此形成表达式树:
在声明中
(unit as RangeUnit).PreferredTarget = UnitType.Melee;
赋值运算符( =
)将位于表达式树的根部,左边和右边的表达式为分支。
当评估左手(分配前)时会发生NullReferenceException
。 此时编译器已经开始评估=
。 由于解引用运算符( .
)将在运行时抛出NullReferenceException
,因此编译器只需继续解析表达式树即可。
另一方面,如果允许这样的陈述:
(unit as RangeUnit)?.PreferredTarget = UnitType.Melee;
...编译器必须发出代码来检查refTypeInstance
的值是否为空。 它可以这样做,但问题是,编译器会如何处理当前正在处理的表达式树? 它不能简单地去像在第一个例子,因为它不得不放弃=
起来的表达式树和.
在树下。 它基本上必须插入两个解析树的选择,一个是左边的?.
当它不是null
时候是null
。 然而,这将会改变控制流程,这绝对不是您对运营商的期望。
或者换句话说:只要?.
只是将操作符的评估短路到表达式树的分支上,您会认为这是预期的行为。 但是在这种情况下,这会改变表达式树中更高级别运算符的行为,这是您绝对不会期望的。
因为他们没有做同样的事情,
如果单位为空(或不是范围单位),则第一个片段将返回null。
如果这是在您尝试设置某些内容时发生的,那么您将无法将null设置为值(并且最终会出现错误)。
链接地址: http://www.djcxy.com/p/75165.html上一篇: C# Null Conditional Operator alternative (conditional assignment)?
下一篇: What is meant by "the null conditional operator short circuits"?