c# - ref 参数和赋值在同一行

标签 c# .net ref-parameters

我最近遇到了一个讨厌的错误,简化后的代码如下所示:

int x = 0;
x += Increment(ref x);

...

private int Increment(ref int parameter) {
    parameter += 1;
    return 1;
}

Increment调用后x的值为1!一旦我发现发生了什么,这很容易解决。我将返回值分配给一个临时变量,然后更新 x。我想知道如何解释这个问题。我忽略了规范中的某些内容还是 C# 的某些方面。

最佳答案

+= 读取左侧参数然后读取右侧参数,因此它读取变量,执行递增方法,对结果求和,然后分配给变量。在这种情况下,它读取 0,计算 1 并具有将变量更改为 1 的副作用,求和为 1,然后为变量赋值 1。 IL 证实了这一点,因为它按顺序显示加载、调用、添加和存储。

将 return 更改为 2 以查看结果是 2,确认该方法的返回值是“坚持”的部分。

因为有人问,这里是通过 LINQPad 的完整 IL 及其注释:

IL_0000:  ldc.i4.0
IL_0001:  stloc.0     // x
IL_0002:  ldloc.0     // x
IL_0003:  ldloca.s    00 // x
IL_0005:  call        UserQuery.Increment
IL_000A:  add
IL_000B:  stloc.0     // x
IL_000C:  ldloc.0     // x
IL_000D:  call        LINQPad.Extensions.Dump

Increment:
IL_0000:  ldarg.0
IL_0001:  dup
IL_0002:  ldind.i4
IL_0003:  ldc.i4.1
IL_0004:  add
IL_0005:  stind.i4
IL_0006:  ldc.i4.2
IL_0007:  ret

请注意,在 IL_000A 行,堆栈包含 x 的加载(加载时为 0)和 Increment 的返回值(为 2)。然后它运行 addSTLoc.0,而不进一步检查 x 的值。

关于c# - ref 参数和赋值在同一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15881689/

相关文章:

c# - MS Dynamics CRM 插件错误 - [A]CrmWebSvc 无法转换为 [B]CrmWebSvc

c# - 为什么 'ref'和 'out'不支持多态?

c# - VS 2013 当前不会命中断点。没有为该文档加载任何符号

c# - 使用 linq 计算按日期和 id 分组的总时间

c# - 为什么将我的目标框架从 ".NET Framework 4 Client Profile"更改为 ".NET framework 4"会给我警告消息?

c# - 我什么时候不应该实现 IDisposable?

c# - 为什么 'ref'和 'out'不支持多态?

c# - 如何为单个项目返回 IEnumerable<T>

c# - 前向查找算法