短路计算跳过条件的前/后增量

本文关键字:计算 条件 短路 | 更新日期: 2023-09-27 18:18:53

那么,如果我有一个表达式:

if (obj != null && i++ % divisor == 0)
{
....
}

objnull,则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();
        }
    }

短路计算跳过条件的前/后增量

这绝对是设计的结果。MSDN州:

x && yx & y对应如果x为假,y不会被求值,因为与运算的结果不管y的值是多少,操作都是假的。这被称为"短路"评估。

所以,不管你的语句是什么,不管它是否有后增量,如果短路,它不会被求值

后增量只是语句的后求值。由于该语句从不求值(它是短路的),因此它被跳过。

一种更直观的思考方式是将if语句想象为嵌套的:

if (obj != null)
{
   if (i++ % divisor == 0)
   {
   ...
   }
}

这里我们立即看到i不会被加1。类似地,当if语句短路时,其行为与上述类似,并且后增量不排队。

是的,这是设计。来自规范:

7.12.1布尔条件逻辑运算符

操作x &&y求值为(bool)x ? (bool)y : false。在换句话说,x首先被求值并转换为bool类型。然后,如果x为真,则计算y并将其转换为bool类型成为操作的结果。的结果操作为false

在你的代码中,y是i++ % divisor == 0,所以如果obj为空,i++将不会被执行。

frameNumber不加1,因为_visualizer != null返回false。因此,代码甚至不需要检查/执行自增和取模操作。

如果你切换检查(即if (_frameNumber++ % 5 == 0 && _visualizer != null)),那么_frameNumber会增加…因为实际执行了操作。

所以,是的:这是想要的行为,这是设计

是的,这是设计。如果右边的计算结果为false,则永远不会计算左边,包括可能发生的任何副作用(例如增量)

操作x && y对应于操作x & y,但只有当xtrue时才对y求值

本;源MSDN

是的,这是旧版本的文档,但是语言更清晰,IMO。

如果你想计算增量,可以使用:

if (_visualizer != null & _frameNumber++ % _config.VisualizerUpdateFrequency == 0)
{
    ...
}

如果你想在visualizer == null时执行自增操作,而不是模数操作:

var _prevFrameNumber = _frameNumber++;
if (_visualizer != null && _prevFrameNumber % _config.VisualizerUpdateFrequency == 0)
{
    ...
}