根据MSDN,System.Int32是不可变的,其成员总是返回新实例。 一些常见的代码,比如for循环,经常需要++操作。 增量是否总是创建新实例并丢弃旧实例?据我所知,这种方法会严重影响性能。我想知道微软是如何实现它的。
顺便说一下,增加线程安全吗?在文档中,它说Int32的所有成员都是线程安全的,但是有interlocked.increment()。
感谢。
答案 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+1
到x
的分配不是。
文档在技术上也是正确的,因为++
不是System.Int32的成员,它是将x++
翻译为x = x + 1
的C#编译器。