为什么在示例1中原始字符串保持不变,并且在示例2中,当在示例3中更改对象实例的字符串属性时,原始实例未被取消?
class A { public string property = "class a"; }
static void Main(string[] args)
{
//Example1
string var = "something";
string[] array = new string[] { var };
array[0] += " again";
// var is unchanged, contents in array slot zero are changed
//Example2
A instance = new A();
object[] array2 = new object[] { instance };
array2[0] = null;
// instance is also unchanged, contents in array slot zero are now null
//Example3
A anotherInstance = new A();
object[] array3 = new object[] { anotherInstance };
(array3[0] as A).property = " else";
// the *propery* of anotherInstance changes as expected
return;
}
答案 0 :(得分:3)
在数组中指定值时,可以创建原始值的副本。您不是要创建字符串本身的副本,而是创建“var”变量值的副本 - 这是一个字符串 reference 。在那段时间之后,变量和数组元素之间没有任何关系 - 它们恰好在之后立即具有相同的值,但它们是独立的。更改数组元素以使其引用不同的对象不会更改变量的值,反之亦然。
特别是,这一行:
array[0] += " again";
不更改现有字符串的内容。相反,它会创建一个 new 字符串,并将该引用分配给array[0]
。
现在在“Example3”中,您没有更改数组元素本身的值 - 您正在更改anotherInstance
和array3[0]
引用的对象的内容。这就像两个人知道同一个房子 - 如果一个人把门涂成红色,另一个人也会看到红色的门。
这与阵列几乎没有关系 - 你也会看到与单个变量相同的效果。有关详细信息,请参阅我的article on reference and value types。
答案 1 :(得分:0)
String
是不可变的。这意味着一旦创建/初始化它们,就不能随后更改它们。当你附加到一个字符串时,会创建一个新字符串,而不是被销毁并重新分配的字符串。
答案 2 :(得分:0)
在第一个示例中,数组的第一个元素是对字符串的引用。然后,您使用+
创建一个新字符串,并将该数组的第一个元素更改为对该新字符串的引用。 var
仍然是对旧字符串的引用,因为您没有更改var
。
在你的第二个例子中,数组的第一个元素是对A实例的引用,你只需更改引用,而不是引用的对象。
在第三个示例中,您不更改引用(您不重新分配array3[0]
,即您永远不会array3[0] = something
),但实际上您更改了引用的对象。此更改也会影响anotherInstance
,因为anotherInstance
和array[0]
都是对同一对象的引用。