C# Null Conditional Operator alternative (conditional assignment)?

The C# null-conditional operator allows for useful short circuiting:

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

Unfortunately the null-conditional operator cannot be used in the same way for short hand assignment, because it returns a value (which cannot be used in left handed assignment):

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

resulting in possible alternative syntax:

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

If the compiler knows that RangedUnit is a reference type (not a value type), why can it not conditionally execute the shorthand syntax

refTypeInstance?.SomeField = value;

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

UPDATE (CONCLUSION):

  • The null-conditional operator cannot be used in the left hand side of an assignment statement because this would violate the expected evaluation logic of an assignment statement's expression tree (short circuiting an assignment operation and not performing it at all)
  • The ideal solution is a new conditional-assignment operator (executes only if the left hand side of an assignment is not null), in essence a 'if not null one assignment one liner'

  • The behavior you are expecting:

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

    Is not possible because of the way operators work. More specifically, you have a problem with operator precedence and how expression trees are formed based on that:

    In the statement

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

    The assignment operator ( = ) would be in the root of the expression tree, with the left and the right expressions as branches.

    A NullReferenceException would occur when the left hand is evaluated (before assignment). At this point the compiler has already started to evaluate the = . Since the dereference operator ( . ) will throw a NullReferenceException at runtime, it is safe for the compiler to just continue parsing the expression tree.

    On the other hand if this statement would permitted:

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

    ...the compiler would have to emit code to check whether the value of refTypeInstance is null. It could do that, but the problem is, what would the compiler do with the expression tree that it is currently going through? It can not simply go on like in the first example, because it would have to discard the = up the expression tree and the . down the tree. It would basically have to insert two alternatives of parsing the tree, one when the left of ?. is null and one when it isn't. That however would be an alteration of the control flow, which is definitely not what you expect from an operator.

    Or to put it differently: when long as ?. just short-circuits the evaluation of operators down its branch of the expression tree, you would consider this an expected behavior. But in this case this would alter the behavior of a operator higher up in the expression tree, which you would definitely not expect.


    Because they're not doing the same thing,

    The first snippet will return null if unit is null (or is not a ranged unit).

    If that were to happen as you were trying to set something then you wouldn't be able to set null to value (and you'd end up with an error).

    链接地址: http://www.djcxy.com/p/75166.html

    上一篇: Socket在异步接收数据时抛出nullreferenceexception

    下一篇: C#空条件运算符替代(有条件赋值)?