C#淺克隆與深克隆(淺拷貝與深拷貝)
阿新 • • 發佈:2021-09-08
(1)淺克隆
在淺克隆中,如果原型物件的成員變數是值型別,將複製一份給克隆物件;如果原型物件的成員變數是引用型別,則將引用物件的地址複製一份給克隆物件,也就是說原型物件和克隆物件的成員變數指向相同的記憶體地址。
簡單來說,在淺克隆中,當物件被複制時只複製它本身和其中包含的值型別的成員變數,而引用型別的成員物件並沒有複製,
通過實現ICloneable介面的Clone()方法,並呼叫MemberwiseClone()方法來實現淺克隆
class Myclss:ICloneable { public int Age{ get; set; }public MyData Data { get; set; } = new MyData(); public object Clone() { return this.MemberwiseClone(); } public class MyData { public int Count { get; set; } } }
(2)深克隆
在深克隆中,無論原型物件的成員變數是值型別還是引用型別,都將複製一份給克隆物件,深克隆將原型物件的所有引用物件也複製一份給克隆物件。
簡單來說,在深克隆中,除了物件本身被複制外,物件所包含的所有成員變數也將複製
在C#語言中,如果需要實現深克隆,可以通過序列化(Serialization)等方式來實現。序列化就是將物件寫到流的過程,寫到流中的物件是原有物件的一個拷貝,而原物件仍然存在於記憶體中。
通過序列化實現的拷貝不僅可以複製物件本身,而且可以複製其引用的成員物件,因此通過序列化將物件寫到一個流中,再從流裡將其讀出來,可以實現深克隆。
需要注意的是能夠實現序列化的物件其類必須實現Serializable介面,否則無法實現序列化操作。
using System.Runtime.Serialization.Formatters.Binary; using System; [Serializable]class MyclssDeep { public int Age { get; set; } public MyData Data { get; set; } = new MyData(); public class MyData { public int Count { get; set; } } public MyclssDeep DeepClone() { //將物件序列化為記憶體中的二進位制流 BinaryFormatter inputFormatter = new BinaryFormatter(); MemoryStream inputStream; using (inputStream = new MemoryStream()) { inputFormatter.Serialize(inputStream, this); } //將二進位制流反序列化為物件 using (MemoryStream outputStream = new MemoryStream(inputStream.ToArray())) { BinaryFormatter outputFormatter = new BinaryFormatter(); return (MyclssDeep)outputFormatter.Deserialize(outputStream); } } }