首先解释下深复制和浅复制的区别:
浅复制:A对象复制后成B对象,A对象中还有成员或者子成员与B对象的成员或者子成员指向同一个内存地址,也就是A和B是不同的对象,但是操作B对象,可能会影响改变A对象
深复制:A对象赋值成B对象后,A和B无任何瓜葛,操作B对象不会对A对象产生任何影响。
用代码来说明下平时写代码的深浅复制:
浅复制:
public class Test
{
public string A { get; set; }
public int B { get; set; }
public override string ToString()
{
return $"A:{A},B:{B}";
}
}
static void Main(string[] args)
{
var list = new List<Test>()
{
new Test(){A="A1",B=1 },
new Test(){ A="A2",B=2}
};
var list_Copy = list.ToList();
list_Copy[0].A = "这是修改后的值";
foreach (var i in list)
{
Console.WriteLine(i);
}
Console.Read();
}
执行结果如下:
从结果可以看到,修改list_Copy的元素的属性值,list中的元素的属性也跟着变了。
深复制,我们使用C#自带的克隆模式来实现:
public class Test:ICloneable
{
public string A { get; set; }
public int B { get; set; }
public object Clone()
{
return this.MemberwiseClone();
}
public override string ToString()
{
return $"A:{A},B:{B}";
}
}
static void Main(string[] args)
{
var list = new List<Test>()
{
new Test(){A="A1",B=1 },
new Test(){ A="A2",B=2}
};
var list_Copy = new List<Test>();
list.ForEach(x => list_Copy.Add(x.Clone() as Test));
list_Copy[0].A = "这是修改后的值";
foreach (var i in list)
{
Console.WriteLine(i);
}
Console.Read();
}
执行结果如下:
可以看到,修改list_Copy的任何元素任何属性,都不会影响到list,但是list与list_Copy中的元素值是相同的,这就是深复制
我们平时写软件,有时候会用到深复制,下面介绍实现深复制的几种方法:
1.利用xml或者Binary序列化,然后再反序列化回来
/// <summary>
/// 使用序列化的方法实现深复制
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="source"></param>
/// <param name="destination"></param>
public static void Copy<T>(T source, ref T destination) where T : class
{
BinaryFormatter binaryFormatter = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
binaryFormatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
destination = (T)binaryFormatter.Deserialize(stream);
stream.Close();
stream.Dispose();
}
2.利用JSON序列化成JSON字符串,然后反序列化回来
public static void Copy<T>(T source, ref T destination) where T : class
{
string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(source);
destination = Newtonsoft.Json.JsonConvert.DeserializeObject<T>(jsonStr);
}
需要说明的是:使用ICloneable或者AutoMapper复制出来的复杂对象处理不好会是浅拷贝,还是序列化来的彻底,我推荐第二种方法,第一种类型有时候类型支持有限