Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 为什么值对象是不可变的并按值复制?_C#_Value Objects - Fatal编程技术网

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

C# 为什么值对象是不可变的并按值复制?,c#,value-objects,C#,Value Objects,根据,C#value对象是不可变的,并且是按属性复制的 如果它们是不可变的,为什么要复制?即使它有助于内存的局部性,但这种优化是否足够普遍,使其成为默认行为 编辑:哦,我想我误解了不变性 那么,不变性是否意味着不能单独修改属性,但可以替换现有对象的整个内部构件?但这是否违反了“如果两件事是相等的,它们将永远是相等的” 所以不可变是否意味着不能单独修改属性,但是可以从现有对象中替换整个内部构件 对 但这是否违反了“如果两件事是相等的,它们将永远是相等的” 不,为什么会这样?如果替换现有对象的内部构

根据,C#value对象是不可变的,并且是按属性复制的

如果它们是不可变的,为什么要复制?即使它有助于内存的局部性,但这种优化是否足够普遍,使其成为默认行为

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

那么,不变性是否意味着不能单独修改属性,但可以替换现有对象的整个内部构件?但这是否违反了“如果两件事是相等的,它们将永远是相等的”

所以不可变是否意味着不能单独修改属性,但是可以从现有对象中替换整个内部构件

但这是否违反了“如果两件事是相等的,它们将永远是相等的”


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

我不同意给定的声明,但我将尝试解释我认为他们打算说什么

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

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
值对象

但这是否违反了“如果两件事是相等的,它们将永远是相等的”

根据他们的解释,这仍然是事实。
s.i=3后
s
是一个全新的值。在分配给
s.i
之前,
s
等于
f()
的结果。在分配给
s.i
之后,
s
本身发生了根本性的变化,它不仅仅是对该对象属性的修改,你得到了一个全新的对象,它永远不等于任何其他对象,除非是偶然的


他们的解释与C#的实际工作方式是一致的,尽管他们的措辞不是我通常所看到的,也不是我所说的。请注意,其他文档可能会提出不同的声明,乍一看似乎与这些声明完全矛盾。

所有内容都是按值复制的,除非您使用
ref
关键字。值类型和引用类型之间的区别是:

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

由于当您将一个变量分配给另一个变量时,值类型是“就地”分配的,因此您实际上是在复制对象的成员。将引用类型变量分配给另一个变量时,就是将引用复制到堆上的同一对象。不管怎样,你总是在复制变量的内容。

我认为那篇文章的措辞很糟糕。它试图说的与它看起来所说的相反。值类型不必是不变的。建议使用,但不是必需的
System.Drawing.Rectangle
不是一成不变的。@DavidSchwartz那篇文章很糟糕;其中包括通常的“结构保存在堆栈中,类存储在堆中”胡说八道。鉴于值对象应该是线程安全的:如果我们都可以访问同一个值对象,并且可以在我不知道的情况下替换其内部,我肯定不会称之为“新对象”。但它是一个新对象。每次替换内部对象时,都会得到一个具有不同内部对象的新对象。若您有一个不可变对象并对其进行了修改,那个么您将通过修改获得一个新的不可变对象。这就是不可变对象的语义。在不同的地址?@leewangzhong是,也不是。引用在同一地址,但它是对不同“引用对象”的引用,在新地址。因此值类型不是不可变的,因此默认情况下不会是线程安全的?