c# - operator++ (int x) 是否每次都创建新实例?

标签 c# immutability

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

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

谢谢。

最佳答案

是也不是。

答案是肯定的,因为:

i++;

等同于:

i = i + 1;

这将等同于此(如果 System.Int32 具有具有此签名的构造函数):

i = new int(i + 1);

但是...

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

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

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

所以,澄清几点:

Does increment always create new instances and discard the old ones?

不——这表明了对值类型工作方式的误解。如果值类型分配在本地堆栈以外的某个空间中,那么说递增一个值“丢弃旧值”才有意义。旧值确实被覆盖,但我认为您不会对此感到惊讶。

By the way, is increment thread-safe? In documentation, it says all the members of Int32 are thread-safe . . .

文档中说 Int32 的所有成员都是线程安全的,这意味着相对于当前值。事实上,任何不可变类型都将是线程安全的,因为如果它不能被修改,那么它就不会被破坏。

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

关于c# - operator++ (int x) 是否每次都创建新实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3540038/

相关文章:

java - 不可变的深拷贝

C# NHibernate - 在删除时删除对对象的所有引用

c# - LINQ 中 select 中的 cast 和 as 之间的区别

c# - 我如何查看我的表单当前是否位于其他表单之上?

java - 有效地 "modifying"一个 ImmutableMap

javascript - Object.freeze 函数有什么理由吗?

c# - 为什么C#中同时存在抽象类和接口(interface)?

c# - 服务合约中的构造函数逻辑

java - 限制类及其成员的可访问性是否是更安全代码的有效做法?

java - Guava 中是否有对应的不可变枚举映射?