operator ++(int x)每次都创建新实例吗?

时间:2010-08-22 03:44:59

标签: c# immutability

根据MSDN,System.Int32是不可变的,其成员总是返回新实例。 一些常见的代码,比如for循环,经常需要++操作。 增量是否总是创建新实例并丢弃旧实例?据我所知,这种方法会严重影响性能。我想知道微软是如何实现它的。

顺便说一下,增加线程安全吗?在文档中,它说Int32的所有成员都是线程安全的,但是有interlocked.increment()。

感谢。

3 个答案:

答案 0 :(得分:3)

是和否。

从这个意义上说答案是肯定的:

i++;

相当于:

i = i + 1;

这相当于此(如果System.Int32有一个带有此签名的构造函数):

i = new int(i + 1);

<强> BUT ...

.NET中值类型的构造函数绝不与引用类型构造函数相同。

值类型的空间在堆栈上分配一次。当您编写i = i + 1时,这只是将新值写入内存中的相同位置。它不是堆上的新分配。

这实际上是一个实现细节;但这并没有改变这样一个事实,即我认为你真正要求的答案 - “写i++是否需要在某处分配一些新内存?” - 问题的答案是否定的。

所以,澄清几点:

  

增量是否总是创建新实例并丢弃旧实例?

不 - 这表明对价值类型的运作方式存在误解。如果在除本地堆栈之外的某些空间中分配值类型,则增加值“丢弃旧值”是唯一有意义的。确实,旧值被覆盖,但我几乎认为你不会觉得这很令人惊讶。

  

顺便说一下,增加线程安全吗?在文档中,它说Int32的所有成员都是线程安全的。 。

如果文档说明Int32的所有成员都是线程安全的,则表示当前值。实际上,任何不可变类型都是线程安全的,因为如果它不能被修改,那么它就不会被破坏。

您必须意识到i++不仅仅是对某些i值的方法调用;它是i赋值到一个新值。此操作 - 将i分配给新的递增值 - 线程安全,因为两个线程可能同时执行此代码并且您最终可以获得新值i只比前一个值大1。这就是Interlocked.Increment的用途。但是MSDN文档不是骗你的;多线程访问不会影响i的内部状态。

答案 1 :(得分:1)

System.Int32不是参考类型。实例不是通过以类的方式分配内存来实例化的。

相反,它是值类型。这意味着每次将整数值分配给变量时都会复制整数值。没有引用整数,只是整数本身。

++运算符以一种在语义上等同于创建新实例的方式返回一个新整数,但它实际上并不为任何对象实例分配内存。

答案 2 :(得分:0)

没有增量(++)不是线程安全的。 MSDN文档是正确的,但令人困惑。你需要关注第二部分。

  

此类型的所有成员都是线程   安全。似乎要修改的成员   实例状态实际上返回一个新的   实例用new初始化   值。 与任何其他类型一样,阅读   并写入共享变量   包含此类型的实例必须   受到锁保护   线程安全。

说的是x+1是线程安全的,因为它本身不会修改x(将其视为创建临时值)。但是x+1x的分配不是。

文档在技术上也是正确的,因为++不是System.Int32的成员,它是将x++翻译为x = x + 1的C#编译器。