所以,如果我有一个表达式:
if (obj != null && i++ % divisor == 0)
{
....
}
且obj
为null
,然后i
永不递增。如果我使用
i++;
if (obj != null && i % divisor == 0)
{
....
}
然后,当然,i
会增加。
这是设计的吗?我从优化的角度理解短路评估,但我(错误地)假设编译器会识别后增量表达式并对其进行评估。
(如果这是在规范中,我找不到它 - 只是在这里寻找一些(喘气)意见。)
更新
这是实际的代码。
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();
}
}
答案 0 :(得分:6)
后增量仅是对陈述的后评估。由于该语句从未被评估(它被短路),所以它被跳过了。
更直观的方式是将if语句想象为嵌套:
if (obj != null)
{
if (i++ % divisor == 0)
{
...
}
}
我们立即看到i
不会增加。类似地,当if
语句被短路时,行为类似于上面的行为,并且后增量不会排队。
答案 1 :(得分:6)
绝对是设计。 MSDN州:
操作
x && y
对应于操作x & y
,除了 如果x为false,则不评估y,因为AND的结果 无论y的值是什么,操作都是假的。这被称为 “短路”评估。
所以,你的陈述是什么并不重要,无论是否有后增量,如果它被短路都不会被评估。
答案 2 :(得分:4)
是的,这是设计的。从规范:
<强> 7.12.1 布尔条件逻辑运算符
操作x&amp;&amp; y被评估为
(bool)x ? (bool)y : false
。在 换句话说,首先评估x并将其转换为bool类型。然后, 如果x为真,则计算y并将其转换为bool类型,并且这样 成为操作的结果。否则,结果了 操作是假的
在您的代码中,y为i++ % divisor == 0
,因此如果i++
为空,则不会执行obj
。
答案 3 :(得分:2)
frameNumber不会递增,因为_visualizer != null
返回false。因此,代码甚至无需检查/执行增量和模运算。
如果你转换支票(即if (_frameNumber++ % 5 == 0 && _visualizer != null)
),那么_frameNumber
会增加......因为实际上已经执行了操作。
所以是的:这是想要的行为,而且是设计的。
答案 4 :(得分:1)
是的,这是设计的。如果右侧评估为false
,则不会评估左侧,包括可能发生的任何副作用(例如增量)
操作
时才评估x && y
对应于操作x & y
,但仅当y
为x
true
-source MSDN
是的,这是文档的旧版本,但语言更清晰,IMO。
如果要评估增量,请使用:
if (_visualizer != null & _frameNumber++ % _config.VisualizerUpdateFrequency == 0)
{
...
}
如果要在visualizer == null
但不是模数:
var _prevFrameNumber = _frameNumber++;
if (_visualizer != null && _prevFrameNumber % _config.VisualizerUpdateFrequency == 0)
{
...
}