C#基礎_深拷貝與淺拷貝
阿新 • • 發佈:2021-10-22
C#基礎_深拷貝與淺拷貝
概念
- 深拷貝:二個獨立的物件,互相沒有影響。B變化,A不跟著變化,反之亦然
- 淺拷貝:二個物件指向的引用地址是一致的,存在著影響。B變化,A也跟著變化,反之亦然
- 其他:值型別只能進行深拷貝,引用型別可以進行深拷貝與淺拷貝。
淺拷貝現象演示:(有二個不同的物件A和B,將B深拷貝A。B變化,B也跟著變化)
物件之間賦值,就會存在淺拷貝的問題
//新建Person類 public class person { public int id { get; set; } public string name { get; set; } public int age { get; set; } public string grade { get; set; } }
//測試 var A = new person() { id = 1, name = "zhangsan1", age = 25, grade = "一年級" }; person B = A; Console.WriteLine("---------------------test1:直接將A賦給B。判斷二個物件是否相等------------------------"); Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}"); Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} "); Console.WriteLine("---------------------test2:給B.ID賦值。判斷A.ID是否改變------------------------"); B.id = 2; ///test2 給B的ID賦值 Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}"); Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} "); Console.WriteLine("---------------------test3:給A.ID賦值。判斷B.ID是否改變------------------------"); A.id = 3; ///test2 給B的ID賦值 Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}"); Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} ");
---------------------test1:直接將A賦給B。判斷二個物件是否相等------------------------ 物件A-->ID:1,name=zhangsan1,age=25,grade=一年級 物件B-->ID:1,name=zhangsan1,age=25,grade=一年級, A=B?True ---------------------test2:給B.ID賦值。判斷A.ID是否改變------------------------ 物件A-->ID:2,name=zhangsan1,age=25,grade=一年級 物件B-->ID:2,name=zhangsan1,age=25,grade=一年級, A=B?True ---------------------test3:給A.ID賦值。判斷B.ID是否改變------------------------ 物件A-->ID:3,name=zhangsan1,age=25,grade=一年級 物件B-->ID:3,name=zhangsan1,age=25,grade=一年級, A=B?True
深拷貝的實現的四種方式
物件賦值,就會存在淺拷貝的問題
1. 利用反射實現
public static T DeepCopy1<T>(T obj)
{
object retval = Activator.CreateInstance(typeof(T));
PropertyInfo[] pis = typeof(T).GetProperties();
foreach (PropertyInfo pi in pis)
{
try { pi.SetValue(retval, pi.GetValue(obj, null), null); }
catch { }
}
return (T)retval;
}
2.利用xml序列化和反序列化實現
類名需要public
public static T DeepCopy2<T>(T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
XmlSerializer xml = new XmlSerializer(typeof(T));
xml.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
retval = xml.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
3.利用二進位制序列化和反序列化實現
在類前加[Serializable]
public static T DeepCopy3<T>(T obj)
{
object retval;
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
//序列化成流
bf.Serialize(ms, obj);
ms.Seek(0, SeekOrigin.Begin);
//反序列化成物件
retval = bf.Deserialize(ms);
ms.Close();
}
return (T)retval;
}
測試
///深拷貝測試
var A = new person() { id = 1, name = "zhangsan1", age = 25, grade = "一年級" };
person B = DeepCopy1(A);///深拷貝
Console.WriteLine("-------------------深拷貝test1:直接將A賦給B。判斷二個物件是否相等--------------------");
Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}");
Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} ");
Console.WriteLine("-------------------深拷貝test2:給B.ID賦值。判斷A.ID是否改變------------------------");
B.id = 2; ///test2 給B的ID賦值
Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}");
Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} ");
Console.WriteLine("-------------------深拷貝test2:給A.ID賦值。判斷B.ID是否改變------------------------");
A.id = 3; ///test2 給B的ID賦值
Console.WriteLine($"物件A-->ID:{A.id},name={A.name},age={A.age},grade={A.grade}");
Console.WriteLine($"物件B-->ID:{B.id},name={B.name},age={B.age},grade={B.grade}, A=B?{A.Equals(B)} ");
int source = 123;
// 值型別賦值內部執行深拷貝
int copy = source;
Console.WriteLine($"值型別-->source:{source},copy={copy},copy=source?{source.Equals(copy)} ");
copy = 567;
Console.WriteLine($"值型別-->source:{source},copy={copy},copy=source?{source.Equals(copy)} ");
---------------------深拷貝test1:直接將A賦給B。判斷二個物件是否相等------------------------
物件A-->ID:1,name=zhangsan1,age=25,grade=一年級
物件B-->ID:1,name=zhangsan1,age=25,grade=一年級, A=B?False
---------------------深拷貝test2:給B.ID賦值。判斷A.ID是否改變------------------------
物件A-->ID:1,name=zhangsan1,age=25,grade=一年級
物件B-->ID:2,name=zhangsan1,age=25,grade=一年級, A=B?False
---------------------深拷貝test2:給A.ID賦值。判斷B.ID是否改變------------------------
物件A-->ID:3,name=zhangsan1,age=25,grade=一年級
物件B-->ID:2,name=zhangsan1,age=25,grade=一年級, A=B?False
值型別-->source:123,copy=123,copy=source?True
值型別-->source:123,copy=567,copy=source?False