克隆是浅层复制的一种方式。 string是引用类型。为什么s2的变化不能影响s1?
private void button3_Click(object sender, EventArgs e)
{
string[] s1 = { "a", "b" };
string[] s2 = new string[2];
s2 = (string[])s1.Clone();
//s2=s1; //when Direct assignment s1 changed too
s2[1] = "e";
foreach (var s in s1)
{
this.richTextBox1.Text += s+",";
}
this.richTextBox1.Text += System.Environment.NewLine;
foreach (var s in s2)
{
this.richTextBox1.Text += s + ",";
}
}
}
输出: A,B, A,E, 当浅拷贝时,它应该是:a,e,a,e
答案 0 :(得分:4)
当你克隆 s1
到s2
时,这些是两个完全独立的对象,住在不同的位置。
s1[1]
包含对b
所占位置的引用,s2[1]
也是如此。然后,您可以为s2[1]
分配不同的引用 - 一个引用到不同的位置。这不会以任何方式影响s1[1]
。
毕竟,你没有改变持有b
的位置。
当您指定s2 = s1;
时,两个变量都指向同一个对象 - 当您更改该对象时,两个变量都会反映变化,因为它们指向同一个位置。
答案 1 :(得分:2)
无论是浅拷贝还是深拷贝,复制总是会创建一个新实例。这意味着更改复制的对象不会影响原始对象。请注意,当我说更改复制的对象时,我的意思是您将一些元素分配给一个全新的实例。如果只更改该元素的某些属性,它可以反映原始数组中的相应元素(当然,如果元素类型是引用类型)。但在这种情况下,元素只是一个字符串,它是不可变的,我们无法改变它。
关于浅拷贝和深拷贝,这里有点MSDN
:
Array的浅表副本仅复制Array的元素,无论它们是引用类型还是值类型,但它不会复制引用引用的对象。新数组中的引用指向与原始数组中的引用指向的相同对象。
相比之下,Array的深层副本会复制元素以及元素直接或间接引用的所有内容。
我想更多地强调这个更改元素的属性并不意味着更改数组。并且更改数组意味着您必须将一些元素分配给一个全新的实例。
答案 2 :(得分:2)
你所要求的是不可能的,因为字符串是不可变的,这意味着它们不能被分配(Why .NET String is immutable?处的更多信息),因此每次分配字符串时,它实际上是创建一个新字符串并替换对象。
如果你想获得你想要的效果,你可能希望将s2指定给s1,这会使它们指向同一个数组,并具有所需的效果。
浅拷贝的一个例子是: (假设定义了label1和label2)
Label[] s1 = new Label[2];
Label[] s2 = new Label[2];
s1[0] = label1;
s1[1] = label2;
for (int i = 0; i < s1.Length; i++)
s2[i] = s1[i];
s2[1].Text = "asdf";
在最终结果中,s1 [1]的Text属性将更改为“asdf”,因为即使数组不同,s1 [1]和s2 [1]也指向同一个对象。
注意: s2 [1] = new Label()不会改变s1 [1]因为对象s2 [1]指向正在改变(基本上是什么s2 [1] =“asdf”;正在OP的代码中做),但那是任何浅拷贝的限制。
答案 3 :(得分:0)
运行以下程序。我想我是对的。 CopyTo以及Clone正在执行卷影复制。
namespace ConsoleApplication5
{
public class Person
{
public static void Main( string[] args)
{
StringBuilder a = new StringBuilder("Vish");
StringBuilder b = new StringBuilder("Krish");
StringBuilder[] arr = new StringBuilder[2] { a,b };
StringBuilder[] copied = new StringBuilder[2];
arr.CopyTo(copied, 0);
StringBuilder[] cloned = arr.Clone() as StringBuilder[];
Console.WriteLine();
copied[1] = copied[1].Append("_AppendedCopy");
cloned[1] = cloned[1].Append("_AppendedClone");
for (int i = 0; i < arr.Length; i++)
Console.WriteLine(arr[i]);
Console.WriteLine();
for (int i = 0; i < copied.Length; i++)
Console.WriteLine(copied[i]);
Console.WriteLine();
for (int i = 0; i < cloned.Length; i++)
Console.WriteLine(cloned[i]);
Console.WriteLine();
Console.ReadKey();
}
}
}