原文链接:https://blog.youkuaiyun.com/ni_zhi/article/details/5764694
C#复制有深度复制和浅度复制,与赋值运算(=)进行复制的比较。
首先,定义一个类Content作为后面要用的字段类型,Content包含一个int型字段Val。
public class Content
{
public int Val;
}
然后,定义值类型MyStruct和MyClass,各包含一个值类型字段和一个引用类型字段。并且它们都支持ICloneable接口,实现了深度复制和浅度复制。
// MyStruct
public struct MyStruct : ICloneable
{
public int Val;
public Content MyContent;
public MyStruct(int val, int contentVal)
{
Val = val;
MyContent = new Content();
MyContent.Val = contentVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
public object Clone()
{
MyStruct clonedStruct = new MyStruct(Val, MyContent.Val);
return clonedStruct;
}
}
// MyClass
public class MyClass : ICloneable
{
public int Val;
public Content MyContent = new Content();
public MyClass(int newVal, int newContentVal)
{
Val = newVal;
MyContent.Val = newContentVal;
}
public object GetCopy()
{
return MemberwiseClone();
}
public object Clone()
{
MyClass clonedClass = new MyClass(Val, MyContent.Val);
return clonedClass;
}
}
接着,Main函数,对MyClass和MyStruct都分别用了三种复制方法,输出它们的值,然后改变源对象的值,再输出。
class Program
{
static void Main(string[] args)
{
// 引用类型复制测试
Console.WriteLine("Reference Type");
MyClass c1 = new MyClass(1, 1);
MyClass c2 = c1; // 赋值复制
MyClass c3 = (MyClass)c1.GetCopy(); // 浅度复制
MyClass c4 = (MyClass)c1.Clone(); // 深度复制
Console.WriteLine("c1, {0}, {1}", c1.Val, c1.MyContent.Val);
Console.WriteLine("c2, {0}, {1}", c2.Val, c2.MyContent.Val);
Console.WriteLine("c3, {0}, {1}", c3.Val, c3.MyContent.Val);
Console.WriteLine("c4, {0}, {1}", c4.Val, c4.MyContent.Val);
c1.Val = 2;
c1.MyContent.Val = 2;
Console.WriteLine("Source c1, {0}, {1}", c1.Val, c1.MyContent.Val);
Console.WriteLine("Assign c2, {0}, {1}", c2.Val, c2.MyContent.Val);
Console.WriteLine("Shallow c3, {0}, {1}", c3.Val, c3.MyContent.Val);
Console.WriteLine("Deep c4, {0}, {1}", c4.Val, c4.MyContent.Val);
Console.WriteLine();
// 值类型复制测试
Console.WriteLine("Value Type");
MyStruct s1 = new MyStruct(1, 1);
MyStruct s2 = s1; // 赋值赋值
MyStruct s3 = (MyStruct)s1.GetCopy(); // 浅度复制
MyStruct s4 = (MyStruct)s1.Clone(); // 深度复制
Console.WriteLine("s1, {0}, {1}", s1.Val, s1.MyContent.Val);
Console.WriteLine("s2, {0}, {1}", s2.Val, s2.MyContent.Val);
Console.WriteLine("s3, {0}, {1}", s3.Val, s3.MyContent.Val);
Console.WriteLine("s4, {0}, {1}", s4.Val, s4.MyContent.Val);
s1.Val = 2;
s1.MyContent.Val = 2;
Console.WriteLine("Source s1, {0}, {1}", s1.Val, s1.MyContent.Val);
Console.WriteLine("Assign s2, {0}, {1}", s2.Val, s2.MyContent.Val);
Console.WriteLine("Shallow s3, {0}, {1}", s3.Val, s3.MyContent.Val);
Console.WriteLine("Deep s4, {0}, {1}", s4.Val, s4.MyContent.Val);
Console.ReadKey();
}
}
最后,结果如图,重要的是红色矩形框中的内容
结论:
对于引用类型的变量,赋值复制后 对源对象值类型字段和引用类型字段的改变 都会反应在目标对象中;对于值类型的变量,赋值复制后 对源对象值类型字段的改变不会反应在目标对象,而对源对象引用类型字段的改变则会反应在目标对象中。