浅复制:在C#中调用 MemberwiseClone() 方法即为浅复制。如果字段是值类型的,则对字段执行逐位复制,如果字段是引用类型的,则复制对象的引用,而不复制对象,因此:原始对象和其副本引用同一个对象!
深复制:如果字段是值类型的,则对字段执行逐位复制,如果字段是引用类型的,则把引用类型的对象指向一个全新的对象!
研究下官方的例子,都加上了注释。
using System;
public class IdInfo
{
public int IdNumber; // 身份证号码
public IdInfo(int IdNumber)
{
this.IdNumber = IdNumber;
}
}
public class Person
{
public int Age; // 年龄
public string Name; // 姓名
public IdInfo IdInfo; // 身份信息
public Person ShallowCopy()
{
return (Person) this.MemberwiseClone(); // 浅复制,只复制对象的字段值,而不复制引用类型的实例
}
public Person DeepCopy()
{
Person other = (Person) this.MemberwiseClone(); // 浅复制,复制对象的字段值
other.IdInfo = new IdInfo(IdInfo.IdNumber); // 创建新的IdInfo对象,并复制原始对象的IdNumber值
other.Name = String.Copy(Name); // 复制原始对象的Name值
return other; // 返回深复制的Person对象
}
}
public class Example
{
public static void Main()
{
// 创建Person实例并为其字段赋值
Person p1 = new Person();
p1.Age = 42;
p1.Name = "Sam";
p1.IdInfo = new IdInfo(6565);
// 执行p1的浅复制并赋值给p2
Person p2 = p1.ShallowCopy();
// 显示p1和p2的值
Console.WriteLine("Original values of p1 and p2:");
Console.WriteLine(" p1 instance values: ");
DisplayValues(p1);
Console.WriteLine(" p2 instance values:");
DisplayValues(p2);
// 修改p1的属性值并显示p1和p2的值
p1.Age = 32;
p1.Name = "Frank";
p1.IdInfo.IdNumber = 7878;
Console.WriteLine("\nValues of p1 and p2 after changes to p1:");
Console.WriteLine(" p1 instance values: ");
DisplayValues(p1);
Console.WriteLine(" p2 instance values:");
DisplayValues(p2);
// 执行p1的深复制并赋值给p3
Person p3 = p1.DeepCopy();
// 修改p1类的成员为新值以展示深复制
p1.Name = "George";
p1.Age = 39;
p1.IdInfo.IdNumber = 8641;
Console.WriteLine("\nValues of p1 and p3 after changes to p1:");
Console.WriteLine(" p1 instance values: ");
DisplayValues(p1);
Console.WriteLine(" p3 instance values:");
DisplayValues(p3);
}
public static void DisplayValues(Person p)
{
Console.WriteLine(" Name: {0:s}, Age: {1:d}", p.Name, p.Age);
Console.WriteLine(" Value: {0:d}", p.IdInfo.IdNumber);
}
}
执行过程就是,先创建p1实例,再执行p1浅复制并赋值给p2,再修改p1的值。结果如下:
无论是浅复制还是深复制,副本中的值类型都是全新的!
浅复制中原始对象和副本的引用类型指向同一内存地址,所以,修改了P1的IdInfo会同时影响P2的IdInfo。
再执行p1浅复制并赋值给p3,再修改p1的值。结果如下:
深复制中原始对象和副本的引用类型指向各自的地址,两者完全是两个不同的对象!
因此:修改P1不会影响P3.
深浅复制主要用于当创建一个对象需要消耗过多资源时,可以采取复制的方法提升效率!
大话设计模式的原话是这样滴:当你New一个对象时,每New一次,都需要执行一个构造函数,如果构造函数的执行时间很长,那么多次New对象时会大大拉低程序执行效率,因此:一般在初始化信息不发生变化的前提下,克隆是最好的办法,这既隐藏了对象的创建细节,又大大提升了性能!
最近开发网关的时候经常用到,就记录一下。