有趣的面试练习结果:返回,后增量和ref行为

Are*_*yst 59 c# increment ref operator-precedence

这是一个简单的控制台应用程序代码,它返回一个我完全不理解的结果.

试着想一想它是否在控制台中输出0,1或2:

using System;

namespace ConsoleApplication
{
    class Program
    {
        static void Main()
        {
            int i = 0;
            i += Increment(ref i);

            Console.WriteLine(i);
            Console.ReadLine();
        }

        static private int Increment(ref int i)
        {
            return i++;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

答案是0.

我不明白的是为什么i++Increment方法上执行的post增量ref(不是在传递的变量的副本上)确实增加了变量,但它稍后会被忽略.

我的意思是在这个视频中:

有人可以解释这个例子以及为什么在调试期间我看到该值增加到1,但它又回到0?

Jak*_*rtz 102

i += Increment(ref i); 相当于

i = i + Increment(ref i);
Run Code Online (Sandbox Code Playgroud)

赋值右侧的表达式从左到右进行计算,因此下一步是

i = 0 + Increment(ref i);
Run Code Online (Sandbox Code Playgroud)

return i++返回当前值i(为0),然后递增i

i = 0 + 0;
Run Code Online (Sandbox Code Playgroud)

在赋值之前,值为i1(在Increment方法中递增),但赋值再次为0.

  • 免责声明:我有一个C++背景,对C#知之甚少.但我对此感到困惑.显然,C#定义强制编译器在类似`i + = f();`的语句中,开始制作`i`值的本地匿名副本,然后调用`f`,它可以(如果有访问权限)知道该变量中剩余的值将被遗忘,因为它会被先前制作的`i`和`f`返回的值的总和覆盖,因此知道变量`i`它想要的所有东西. .非常好奇.似乎违背了使`+ =`简单快速的想法. (8认同)
  • 不,我认为它的定义很明确.虽然C++标准基本上(并且懒惰地)将`var + = expr`定义为等同于`var = var + expr`,但它确实产生了两个例外:左值`var`仅被评估一次,并且"相对于不确定的 - 顺序函数调用,复合赋值的操作是单一的评估".这并不完全清楚,但似乎禁止在之前使用`var`获取以及在函数调用之后存储`var`来实现操作.如果您关心,请参阅http://stackoverflow.com/q/24194076/1436796. (4认同)
  • @MarcvanLeeuwen如果将评估顺序从左到右严格定义,那就没有意义.给定`var = var + expr`和从左到右的求值,在评估`expr`之前总会检查`var`,因此`expr`对`var`的任何改变都不会反映在它中.我猜C#只是为它定义比C++更严格的排序,或者其他东西. (4认同)
  • ......你比我快一点;) (3认同)

Dar*_*l42 18

我认为这里的"魔术"只是操作优先操作的顺序

i += Increment(ref i)
Run Code Online (Sandbox Code Playgroud)

是相同的

i = i + Increment(ref i)
Run Code Online (Sandbox Code Playgroud)

+操作从左到右执行

所以首先我们拿...我当时是0 ...

然后我们添加Increment(ref i)的结果......这也是0 ... 0 + 0 = 0 ...但等待......在得到那个结果之前我实际上是递增的...

这个增量发生在我们+操作的左操作数被评估后...所以它不会改变一个东西... 0 + 0仍然是0 ...因此我在+操作被执行后被赋值为0

  • 我仔细阅读.你写的很糟糕.使用正确的术语 - 操作顺序,而不是优先顺序.优先级确定如何从其他模糊输入构造AST.操作/评估顺序决定了如何评估AST的结果.使用短语'operation precedence'表示两者都不是. (4认同)
  • 与优先权无关,与从左到右的评估无关. (3认同)