C#淺拷貝和深拷貝實例解析
在有些時候,我們需要從數(shù)據(jù)庫讀取數(shù)據(jù)填充對象或從硬盤讀取文件填充對象,但是這樣做相對耗時。這時候我們就想到了對象的拷貝。本文即以實例形式解析了C#淺拷貝和深拷貝的用法。具體如下:
一、淺拷貝
1.什么是"淺拷貝":
當針對一個對象前拷貝的時候,對于對象的值類型成員,會復制其本身,對于對象的引用類型成員,僅僅復制對象引用,這個引用指向托管堆上的對象實例。
2.有一個對象,包含引用類型的類成員和值類型的struct成員
Cinema包含引用類型成員Room和值類型成員Film。
public class Room { public int _maxSeat; public Room(int maxSeat) { this._maxSeat = maxSeat; } } public struct Film { public string _name; public Film(string name) { this._name = name; } } public class Cinema { public Room _room; public Film _film; public Cinema(Room room, Film film) { this._room = room; this._film = film; } public object Clone() { return MemberwiseClone(); //對引用類型實施淺復制 } }
3.測試拷貝后的效果
①打印出原先對象拷貝前值類型和引用類型成員的值
②對原先對象拷貝,打印出復制對象值類型和引用類型成員的值
③改變原先對象的值,再次打印原先對象的值類型和引用類型成員的值
④再次打印復制對象值類型和引用類型成員的值
static void Main(string[] args) { Room room1 = new Room(60); Film film1 = new Film("家園防線"); Cinema cinema1 = new Cinema(room1, film1); Cinema cinema2 = (Cinema)cinema1.Clone(); Console.WriteLine("拷貝之前,結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema1._film._name,cinema1._room._maxSeat); Console.WriteLine("拷貝之后,新的結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat); //修改拷貝之前引用類型的字段值 cinema1._film._name = "極品飛車"; cinema1._room._maxSeat = 80; Console.WriteLine("修改之后,結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema1._film._name, cinema1._room._maxSeat); Console.WriteLine("修改之后,新的結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat); Console.ReadKey(); }
運行結果如下:
分析:
淺拷貝關鍵點是對引用類型拷貝的是對象引用,這個引用指向托管堆上的對象實例。改變原對應引用類型的值,會影響到復制對象。
二、深拷貝
1.什么是"深拷貝"
對引用成員指向的對象也進行復制,在托管堆上賦值原先對象實例所包含的數(shù)據(jù),再在托管堆上創(chuàng)建新的對象實例。
2.通過對每個對象成員進行復制進行深拷貝
public object Clone() { Room room = new Room(); room._maxSeat = this._room._maxSeat;//復制當前引用類型成員的值到新對象 Film film = this._film; //值類型直接賦值 Cinema cinema = new Cinema(room, film); return cinema; }
3.也可以通過序列化和反序列化進行深拷貝
public object Clone1() { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, this); //復制到流中 ms.Position = 0; return (bf.Deserialize(ms)); }
4.采用序列化和反序列化深拷貝,但必須把所有的類打上[Serializable],測試代碼如下:
[Serializable] public class Room { public int _maxSeat; public Room() {} public Room(int maxSeat) { this._maxSeat = maxSeat; } } [Serializable] public struct Film { public string _name; public Film(string name) { this._name = name; } } [Serializable] public class Cinema { public Room _room; public Film _film; public Cinema(Room room, Film film) { this._room = room; this._film = film; } //淺拷貝 //public object Clone() //{ // return MemberwiseClone(); //對引用類型實施淺復制 //} //深拷貝 對每個對象成員進行復制 public object Clone() { Room room = new Room(); room._maxSeat = this._room._maxSeat;//復制當前引用類型成員的值到新對象 Film film = this._film; //值類型直接賦值 Cinema cinema = new Cinema(room, film); return cinema; } //使用序列化和反序列化進行復制 public object Clone1() { BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, this); //復制到流中 ms.Position = 0; return (bf.Deserialize(ms)); } }
5.測試拷貝后的效果
①打印出原先對象拷貝前值類型和引用類型成員的值
②對原先對象拷貝,打印出復制對象值類型和引用類型成員的值
③改變原先對象的值,再次打印原先對象的值類型和引用類型成員的值
④再次打印復制對象值類型和引用類型成員的值
static void Main(string[] args) { Room room1 = new Room(60); Film film1 = new Film("家園防線"); Cinema cinema1 = new Cinema(room1, film1); Cinema cinema2 = (Cinema)cinema1.Clone1(); Console.WriteLine("拷貝之前,結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema1._film._name,cinema1._room._maxSeat); Console.WriteLine("拷貝之后,新的結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat); //修改拷貝之前引用類型的字段值 cinema1._film._name = "極品飛車"; cinema1._room._maxSeat = 80; Console.WriteLine("修改之后,結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema1._film._name, cinema1._room._maxSeat); Console.WriteLine("修改之后,新的結構成員的字段值為{0},引用類型成員的字段值為{1}", cinema2._film._name, cinema2._room._maxSeat); Console.ReadKey(); }
結果:
分析:
深拷貝后,兩個對象的引用成員已經(jīng)分離,改變原先對象引用類型成員的值并不會對復制對象的引用類型成員值造成影響。
相關文章
C#使用Excel動態(tài)函數(shù)實現(xiàn)生成依賴列表
這篇文章主要為大家詳細介紹了如何在C#中使用?Excel?動態(tài)函數(shù)生成依賴列表,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學習一下2024-02-02C#實現(xiàn)應用程序的監(jiān)控與調(diào)試的示例代碼
日志記錄是軟件開發(fā)中不可或缺的功能,它能幫助開發(fā)者在應用程序運行時記錄重要信息,本文就來介紹一下常用日志記錄功能以及常用的日志庫,感興趣的可以了解一下2024-03-03