有趣的面试练习结果:return、post increment 和 ref 行为 [重复]
Posted
技术标签:
【中文标题】有趣的面试练习结果:return、post increment 和 ref 行为 [重复]【英文标题】:Interesting interview exercise result: return, post increment and ref behavior [duplicate] 【发布时间】:2017-09-18 06:42:50 【问题描述】:这是一个简单的控制台应用程序代码,它返回的结果我完全看不懂。
试想一下它在控制台输出的是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++;
答案是 0。
我不明白为什么在Increment
方法上执行i++
后增量i++
,该方法在ref
上执行(而不是在传递的变量的副本上)确实增加了变量,但它只是稍后会被忽略。
我的意思是在这个视频中:
有人能解释一下这个例子吗?为什么在调试过程中我看到值递增到 1,然后又回到 0?
【问题讨论】:
在执行return i++
时,i 的值(即 0)在递增之前返回。虽然可能会发生增量,但该值被丢弃,因为它已经返回。尝试改用return ++i;
。
虽然这是一个答案谜题,但它是一个非常愚蠢的面试问题,IMO。它应该被标记为“语言律师”,因为这种行为取决于一个非常小众的语言规则,你希望永远不会在行动中遵守,因为(希望)你在实践中永远不会看到这样的代码
@Alexander 同意了。如果为我工作的人写了这样的代码,我会坐下来和他们“交谈”
一些相关的问题,也提供了一些关于幕后发生的事情的好信息:***.com/questions/33783989/…
如果我在面试中得到了这段代码,我的第一个答案是:“我可以为这段代码编写测试(如果它们不存在的话),然后将它重构为理智吗?”
【参考方案1】:
i += Increment(ref i);
等价于
i = i + Increment(ref i);
赋值右边的表达式是从左到右求值的,所以下一步是
i = 0 + Increment(ref i);
return i++
返回i
的当前值(即0),然后递增i
i = 0 + 0;
在赋值之前,i
的值是 1(在 Increment
方法中递增),但赋值又使它变为 0。
【讨论】:
...你比我快一点;) 谢谢你,Jakub,详细信息,现在为什么它是 1 又变成 0 是有道理的。 免责声明:我有 C++ 背景,对 C# 知之甚少。但我对此感到困惑。所以显然 C# 定义强制编译器,在像i+=f();
这样的语句中,开始制作i
值的本地匿名副本,然后调用f
,它可以(如果它可以访问)愚弄变量i
它想要的一切,知道留在该变量中的值无论如何都会被遗忘,因为它将被i
之前制作的匿名副本和f
返回的值之和覆盖。非常好奇。似乎与使+=
简单快速的想法背道而驰。
不,我想它会很好定义。虽然 C++ 标准基本上(并且懒惰地)将var+=expr
定义为等同于var=var+expr
,但它确实有两个例外:左值var
仅评估一次,并且“对于不确定顺序的函数调用,操作复合分配是一个单一的评估”。这并不完全清楚,但它似乎确实禁止在函数调用之前使用var
的提取和函数调用之后的var
的存储来实现该操作。如果您关心,请参阅***.com/q/24194076/1436796。
@MarcvanLeeuwen 如果评估顺序被定义为严格从左到右是有意义的。鉴于var = var + expr
和从左到右的评估,var
将始终在评估expr
之前检查,因此expr
对var
所做的任何更改都不会反映在其中。我猜 C# 只是为它定义了比 C++ 更严格的排序。【参考方案2】:
我认为这里的“魔法”只是操作优先级操作的顺序
i += Increment(ref i)
和
一样i = i + Increment(ref i)
+操作从左到右执行
所以首先我们取 i ... 当时是 0 ...
然后我们添加 Increment(ref i) 的结果 ... 这也是 0 ... 0+0=0 ... 但是等待 ... 在我们得到结果之前 i 实际上是递增的 ...
该增量发生在我们的 + 操作的左操作数被评估之后......所以它不会改变任何东西...... 0+0 仍然是 0......因此在 + 操作之后 i 被分配为 0被处决
【讨论】:
与优先级无关,与从左到右的评估有关。 仔细阅读...运算符优先级!=操作优先级...导致从左到右的顺序... 我仔细阅读了。你写的不好。使用正确的术语 - 操作顺序,而不是优先级。优先级决定了 AST 如何从其他不明确的输入中构建。操作/评估的顺序决定了如何将 AST 评估为结果。使用短语“操作优先级”意味着两者都不是。 嗯...谢谢你的英语词汇课...【参考方案3】:正如您所提到的 - 后增量“i++”。声明 - “返回 i++;”返回原始值后将在内存中设置'i'的值。
尝试使用“return ++i;”也许你会得到它。
【讨论】:
我不认为这是正确的。语句return i++;
递增 i
,然后返回 i
的前一个值,即 0。我从 Eric Lippert 的回答中获得该信息:***.com/questions/3346450/…以上是关于有趣的面试练习结果:return、post increment 和 ref 行为 [重复]的主要内容,如果未能解决你的问题,请参考以下文章