为什么值对象是不可变的并且按值复制?

时间:2014-08-07 21:38:56

标签: c# value-objects

根据Wikipedia's article on value objects,C#值对象既是不可变的,也是属性复制的。

如果他们不可变,为什么要复制?即使它有助于内存局部性,这是否足以使其成为默认行为?

编辑:哦,我想我误解了不变性。

不变性意味着您无法单独修改属性,但是您可以从现有对象替换整个内部结构吗?但是没有违反"如果两件事情相等,他们将永远是平等的#34;

3 个答案:

答案 0 :(得分:0)

  

不变性意味着您无法单独修改属性,但是您可以从现有对象替换整个内部结构吗?

  

但是没有违反"如果两件事情相等,他们将永远是平等的#34;

没有。为什么会这样?如果从现有对象替换内部,则会得到一个具有不同内部的新对象。

答案 1 :(得分:0)

我不同意给定的说法,但我会尝试解释我认为他们打算说的话。

结构类型是不可变的这一事实意味着

public struct S { int i; }
public S f() { /* omitted */ }
public void g() { f().i = 3; }

是一个编译时错误:修改f()的结果是没有意义的,因为修改会立即丢失。

相比之下,

public struct S { int i; }
public S f() { /* omitted */ }
public void g() { var s = f(); s.i = 3; }

很好,但s.i = 3;可以解释为重写所有s:它可以被解释为等同于(伪代码)s = { 3 };,其中{ 3 }构造一个全新的S值对象。

  

但是没有违反"如果两件事情相等,他们将永远是平等的#34;

根据他们的解释,这仍然是正确的。在s.i = 3;之后,s是一个全新的值。在分配到s.i之前,s等于f()的结果。在分配到s.i之后,s本身发生了根本性的变化,并且它不仅仅是对该对象属性的修改,而且还有一个全新的对象,等于任何其他物体,除非是偶然的。

他们的解释与C#的实际效果一致,尽管他们的措辞不是我通常看到的,或者我会如何表达。请注意,其他文档可能会提出不同的声明,乍一看似乎完全与这些声明相矛盾。

答案 2 :(得分:0)

除非您使用ref关键字,否则

所有内容都会按值进行复制。值类型和引用类型之间的区别是:

  • 类型为值类型的变量/字段将被分配声明它们的位置。如果它们是局部方法变量,则它可以是当前堆栈帧。但如果它们是已经在堆上的对象的一部分,它也可以是堆。
  • 类型为reference-type的变量/字段包含对堆上分配的对象的引用。

由于在将变量分配给另一个变量时,值类型是“就地”分配的,因此您实际上是在复制对象的成员。将引用类型变量分配给另一个时,您将复制对堆上同一对象的引用。无论哪种方式,您总是复制变量的内容。