【问题标题】:Post-increment x by n (n != 1)将 x 后递增 n (n != 1)
【发布时间】:2013-12-26 03:23:17
【问题描述】:

所以,如果我执行以下代码...

int x = 0;
Debug.WriteLine(x++);
Debug.WriteLine(x += 4);
Debug.WriteLine(x);

...我分别得到 0、5 和 5。但是,我想要得到的是 0、1 和 5。有没有办法在 C# 中按 n 进行后增量?还是我必须将 += 作为自己的语句写出来?

就上下文而言,我实际上正在做的是缓冲区上的一堆 BitConverter 操作,将每个操作都作为一个自给自足的语句,其中偏移量增加了转换为的数据类型。这样,如果以后更改缓冲区格式,我可以只添加或删除一行,而不必担心任何周围的代码。

【问题讨论】:

  • 我会说这是不可能的。
  • 我很清楚,你想增加一个以上吗?
  • 使用你的例子,你永远不会从这三个WriteLines 中得到一个zero 和一个one
  • 奥尔登:是的,这就是我想做的。
  • @JeroenVannevel:不,++x 等同于x += 1x++ 不能使用 += 写入。

标签: c# post-increment


【解决方案1】:

您应该能够滥用Interlocked.Exchange 来获取变量的旧值,同时替换它的值:

Debug.WriteLine(Interlocked.Exchange(ref x, x+4));

换句话说,将变量x的值替换为x + 4,但返回x的前一个值。

编辑:

反汇编显示这个“以 4 为增量并交换”是在 4 条指令中完成的 - 根本不需要调用,所以性能应该不错:

            Interlocked.Exchange(ref x, x + 4);
0000005e  mov         eax,dword ptr [rbp+2Ch] 
00000061  add         eax,4 
00000064  xchg        eax,dword ptr [rbp+2Ch] 
00000067  mov         dword ptr [rbp+28h],eax 

这种(和其他)解决方案的非直观性质可能归结为违反CQS principle - 我们正在改变一个变量并返回一个值一下子,即我们不应该在主流中做的事情。

【讨论】:

  • 这也很好。不直观,恕我直言:您应该动动脑筋才能理解这条线的目的。
  • 我刚刚学到了一些新东西。我将试一试,看看它与仅使用 x += 4 作为单独操作相比的性能如何。毕竟,我总是可以将其写为行尾的语句,并告诉 StyleCop 当它抱怨一行中有多个语句时该怎么办。 :) 不过,这基本上是一个长期运行的操作的核心,所以最快的就是胜利!
  • 刚刚测试了一下,性能与编写自定义函数相当,但不足为奇的是,比仅仅添加额外的 x += 4 慢。
  • 联锁操作可能比这里需要的要昂贵得多。此外,它们仅在一个参数是内存位置时才有效。在这样的代码中,x 应该在一个寄存器中。并非所有 4 个指令序列都是一样的。我敢猜测,只有当该函数没有内联时,其性能才接近自定义函数。
  • 如果你要在某个地方调用一个方法来完成这项工作,我宁愿为此创建一个具有正确名称的专用方法。
【解决方案2】:

据我所知,这是不可能的。你可以这样写你的包装方法:

static void ExecuteWithPost(ref int value, Action<int> operation, Func<int, int> postOperation)
{
    operation(value);
    value = postOperation(value);
}

并使用它:

int i = 0;
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 1);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x + 4);
ExecuteWithPost(ref i, x => Debug.WriteLine(x), x => x);

打印你想要的。

包装器方法可以是通用的,以使其适用于int以外的类型:

static void ExecuteWithPost<T>(ref T value, Action<T> operation, Func<T, T> postOperation)
{
    operation(value);
    value = postOperation(value);
}

【讨论】:

  • 我的赞成票:我会写这样的东西。我只是不喜欢“ref”,我更愿意返回更新后的值。只是味道而已。
  • 我想过做这样的事情,但认为它可能会增加太多的开销。不过,我喜欢你的解决方案,比我的解决方案更通用、更优雅!
【解决方案3】:

运算符++x = x + 1; 的缩写形式,因此使用+= 不是一个坏主意:

如果我理解正确的话:

int x = 0;
Debug.WriteLine(x++);  //return 0
Debug.WriteLine(x);  //return 1
Debug.WriteLine(x += 4);  //return 5

我建议您使用运算符+=,因为任何其他方式运算符重载或其他方式;只会是开销。

【讨论】:

  • 这不是像 x++ 那样的“后增量 4”,而是增量 4。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-18
  • 1970-01-01
  • 2019-04-15
  • 1970-01-01
  • 2022-06-10
  • 1970-01-01
相关资源
最近更新 更多