Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/github/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 短路评估跳过条件中的前/后增量_C#_Compilation - Fatal编程技术网

C# 短路评估跳过条件中的前/后增量

C# 短路评估跳过条件中的前/后增量,c#,compilation,C#,Compilation,所以,如果我有一个表达式,比如: if (obj != null && i++ % divisor == 0) { .... } 而obj为null,则i从不递增。如果我使用 i++; if (obj != null && i % divisor == 0) { .... } 当然,i是递增的 这是故意的吗?我从优化的角度理解短路计算,但我(错误地)假设编译器会识别增量后表达式并对其进行计算 (如果这是在规范中,我找不到它-只是在这里寻找一些(喘息)意见。)

所以,如果我有一个表达式,比如:

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();

        }

    }

后增量只是语句的后评估。由于从未对语句求值(语句短路),因此跳过了该语句

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

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

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

这是设计的必然结果。国家:

操作
x&y
与操作
x&y
相对应,除了 如果x为false,则不计算y,因为 无论y的值是多少,运算都是false。这被称为 “短路”评估


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

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

操作
x&&y
与操作
x&y
相对应,但只有当
x
true

-来源

是的,这是一个旧版本的文档,但语言更清晰,国际海事组织

如果要计算增量,请使用以下方法:

if (_visualizer != null & _frameNumber++ % _config.VisualizerUpdateFrequency == 0)
{
    ...
}
如果您希望在
visualizer==null
但不是模数时执行增量:

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

由于
\u visualizer!=null
返回false。因此,代码甚至不必检查/执行增量和模运算

如果要切换检查(即
如果(\u frameNumber++%5==0&&&u visualizer!=null)
),则
\u frameNumber
将递增。。。因为这个动作实际上是执行的


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

是的,这是设计的。根据规范:

7.12.1 布尔条件逻辑运算符

操作x&&y被评估为
(bool)x?(bool)y:false
。在里面 换句话说,首先计算x并将其转换为bool类型。那么, 如果x为true,则计算y并将其转换为bool类型,并且 成为操作的结果。否则,将导致 手术是假的


在您的代码中,y是
i++%divisior==0
,因此如果
obj
为空,则不会执行
i++

如果您想要这种行为,可以使用
&
。如果您必须问这个问题,则表明您的代码不可读。简单。其他人在阅读代码时也会有同样的问题。我建议您构造代码,这样就不会出现这个问题。当然,行为是正确的。你是在误解短路行为是一种优化的情况下工作的。不是这样的事;这是一个重要的保证。如果是可选的优化,那么您不能保证
如果(obj!=null&&obj.ToString().Length>10)
不会崩溃@约翰的忠告是好的忠告;这段代码很难阅读,风格也不好。如果您不理解C#中运算符的含义,那么(1)自我教育,(2)编写代码,让不理解其含义的人更容易阅读和维护。一个很好的经验法则是,每个表达式应该完全没有副作用——表达式应该对其值有用,而不是对其效果有用——并且每个单独的语句应该只产生一个副作用。有多重副作用的语句很难解释。@davidlive:正是因为它修改了状态后的表达式才不能执行它!短路操作的全部要点是防止产生右手侧的副作用。@EricLippert我明白了,这当然是有道理的。然而,我的咖啡/啤酒色的《龙之书》让我对这个结构的目的和语义含义有了截然不同的解释。同样,我理解这是一种糟糕的风格——问题是生成代码的“正确性”。(作为一名EE,过去曾在编译器团队(Keil)工作过,我意识到这种级别的“bug”几乎从未在成熟的工具中出现过。因此,我感到困惑。)