首先解釋下深複製和淺複製的區別:
淺複製: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複製出來的複雜對象處理不好會是淺拷貝,還是序列化來的徹底,我推薦第二種方法,第一種類型有時候類型支持有限