一、概念
深拷贝:复制对象中所有值类型和引用类型的字段的值,副本是重新创建的一个对象,对象中字段只是复制的所有字段的值,没有复制引用。所以副本对象内的值并不会因为源对象数据的值的修改而改变。
浅拷贝:同样会复制对象中所有值类型,但是引用类型复制的是引用,所以在源对象数据中如果引用类型数据变化了,副本中的数据也会变化。
值的一提的是,string类型理论上是引用类型,但是表现上是值类型,因为字符串类型的唯一性。
二、微软已提供的接口和方法
MemberwiseClone 方法:创建当前 System.Object 的浅表副本(浅拷贝),它是object类型的一个保护类型的方法,只能在其派生类的内部使用。
ICloneable 接口:只包含一个Clone方法。具体实现自定义,但是一般是深拷贝,因为浅拷贝已经提供了一个方法。
三、示例
public class Person : ICloneable
{
public string Name { get; set; }
public uint Age { get; set; }
public byte[] Data { get; set; }
//DeepCopy
public object Clone()
{
byte[] data = new byte[3];
this.Data.CopyTo(data, 0);//这里只需要拷贝源对象的数据,不需要拷贝引用
Person person = new Person
{
Name = this.Name,
Age = this.Age,
Data = data,//所以不能在这里直接赋值
};
return person;
}
//ShallowCopy
public Person ShallowCopy()
{
return (Person)this.MemberwiseClone();
}
public override string ToString()
{
return $"{Name} {Age} {BitConverter.ToString(Data)}";
}
}
另外还有一种通用的深拷贝方式,用到了序列化:
public static T DeepClone<T>(this T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
使用的时候需要把T类型加上[Serialize]特性