"|=" operator caches static field value?

Viewed 60

I was having an interesting bug with changes not being registered. The fix was unusual. The first code works fine, while the second one - doesn't.

https://rextester.com/PIRZFJ12810

globChanged = false;

bool tmp = target.Inspect();
globChanged |= tmp;  
 
if (globChanged) Debug.LogError("Works!");

This one doesn't work:

globChanged = false;

globChanged |= target.Inspect();

if (globChanged) Debug.LogError("Works!");
           

I think I have a suspicion. globChanged is a public static field. The target.Inspect(); actually returns False. But internally it sets globChanged = true when changes are made. I think the operator "|=" evaluates the value of globChanged before the Inspect(); function was called. And I actually tested this - at the end of target.Inspect(); the globChanged is True.

Also: Doesn't work:

  globChanged = globChanged || pgi.Inspect();   

Works:

globChanged = pgi.Inspect() || globChanged;

To clarify. Doesn't work means that It returns False when globChanged was set True. pgi.Inspect(); is executed every time and globChanged is False at the start.

1 Answers

The expression value |= DoSomething is nothing but this:

_value = _value | DoSomething

In your first example you set tmp to whatever Inspect returns - false. However that method also sets globalChange to true. Afterwards globalChange is evaluated in the next line. It is now true, which results in true | false.

The second example is a bit more tricky.

From the docs:

The | operator evaluates both operands even if the left-hand operand evaluates to true, so that the operation result is true regardless of the value of the right-hand operand.

As mentioned here both expressions are evaluated from the left to the right. So first _gloablChange is evaluated, which is false, as of its initial value. Afterwards the second operand is evaluated. It also returns false, even though it has some side-effect. That side-effect however is irrelevant as the value of globalChange already was evelauted before. Thus false | false just returns false.

The ||-operator on the other hand is short-circuiting, which means the right part is only evaluated if the left one is false.

Related