Reputation: 29051
So, if I have an expression like:
if (obj != null && i++ % divisor == 0)
{
....
}
and obj
is null
, then i
is never incremented. If I use
i++;
if (obj != null && i % divisor == 0)
{
....
}
instead, then, of course, i
is incremented.
Is this by design? I understand short-circuit evaluation from an optimization point of view, but I had (incorrectly) assumed that the compiler would recognize the post-increment expression and evaluate it regardless.
(If this is in the spec, I couldn't find it - just looking for some (gasp) opinions here.)
Update
Here's the actual code.
private int _frameNumber = 0;
private void simulator_OnFrameEnd(object sender, System.EventArgs e)
{
_frameNumber++;
if (_visualizer != null && _frameNumber % _config.VisualizerUpdateFrequency == 0)
{
var field = _simulator.GetField(_config.PreviewField);
_visualizer.Update(field, _simulator.FrameTime);
}
if (_frameNumber % _config.OptimizerRegridFrequency == 0)
{
_simulator.UpdateFieldGrids();
}
}
Upvotes: 2
Views: 387
Reputation: 149050
Yes, it's by design. The left side is never evaluated if the right side evaluates to false
, including any side effects that might occur (such as the increment)
The operation
x && y
corresponds to the operationx & y
, except thaty
is evaluated only ifx
istrue
—source MSDN
Yes that's an older version of the documentation, but the language is clearer, IMO.
If you want the increment to be evaluated use this:
if (_visualizer != null & _frameNumber++ % _config.VisualizerUpdateFrequency == 0)
{
...
}
If you want to perform the increment even when visualizer == null
but not the modulus:
var _prevFrameNumber = _frameNumber++;
if (_visualizer != null && _prevFrameNumber % _config.VisualizerUpdateFrequency == 0)
{
...
}
Upvotes: 1
Reputation: 144206
Yes, this is by design. From the specification:
7.12.1 Boolean conditional logical operators
The operation x && y is evaluated as
(bool)x ? (bool)y : false
. In other words, x is first evaluated and converted to type bool . Then, if x is true , y is evaluated and converted to type bool , and this becomes the result of the operation. Otherwise, the result of the operation is false
In your code, y is i++ % divisor == 0
so i++
will not be executed if obj
is null.
Upvotes: 4
Reputation: 3417
The frameNumber is not incremented because _visualizer != null
returns false. So the code doesn't even bother to check/excecute the increment and modulo operation.
If you'd switch the checks around (ie if (_frameNumber++ % 5 == 0 && _visualizer != null)
) then _frameNumber
gets incremented... because the operaion actually is executed.
So yes: This is wanted behavior and it is by design.
Upvotes: 2
Reputation: 23142
It is most definitely by design. MSDN states:
The operation
x && y
corresponds to the operationx & y
except that if x is false, y is not evaluated, because the result of the AND operation is false no matter what the value of y is. This is known as "short-circuit" evaluation.
So, it doesn't matter what your statement is, whether it has a post-increment or not, it won't be evaluated if it's short-circuited.
Upvotes: 6
Reputation: 3248
The post-increment is only post evaluation of the statement. Since the statement is never evaluated (it's short circuited) it's skipped.
A more visual way to think of it is to imagine the if statement as being nested:
if (obj != null)
{
if (i++ % divisor == 0)
{
...
}
}
Here we see immediately that i
will not be incremented. Similarly when an if
statement is short circuited the behaviour is similar to the above and the post increment is not queued.
Upvotes: 6