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,则执行该语句)

更新(结论):

  • 无效条件运算符不能用在赋值语句的左侧,因为这会违反赋值语句的表达式树的预期评估逻辑(短路赋值操作并根本不执行)
  • 理想的解决方案是一个新的条件赋值运算符(只有当赋值的左边不为空时才执行),实质上是'if not null one assignment one liner'

  • 您期待的行为:

    (即,如果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"?