亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

淺析C#深拷貝與淺拷貝

2019-11-11 04:48:55
字體:
來源:轉載
供稿:網友
1.深拷貝與淺拷貝         拷貝即是通常所說的復制(Copy)或克隆(Clone),對象的拷貝也就是從現有對象復制一個“一模一樣”的新對象出來。雖然都是復制對象,但是不同的 復制方法,復制出來的新對象卻并非完全一模一樣,對象內部存在著一些差異。通常的拷貝方法有兩種,即深拷貝和淺拷貝,那二者之間有何區別呢?MSDN里對 IClone接口的Clone方法有這樣的說明:在深層副本中,所有的對象都是重復的;而在淺表副本中,只有頂級對象是重復的,并且頂級以下的對象包含引 用??梢钥闯?,深拷貝和淺拷貝之間的區別在于是否復制了子對象。這如何理解呢?下面我通過帶有子對象的代碼來驗證二者的區別。        首先定義兩個類型:Student和ClassRoom,其中Student類型里包含ClassRoom,并使這兩個類型都分別實現自定義的深拷貝接口(IDeepCopy)和淺拷貝接口(IShallowCopy)。類圖如下:

定義代碼如下:

/// <summary>    /// 深拷貝接口    /// </summary>    interface IDeepCopy    {        object DeepCopy();    }    /// <summary>    /// 淺拷貝接口    /// </summary>    interface IShallowCopy    {        object ShallowCopy();    }    /// <summary>    /// 教室信息    /// </summary>    class ClassRoom : IDeepCopy, IShallowCopy    {        public int RoomID = 1;        public string RoomName = "Room1";        public override string ToString()        {            return "RoomID=" + RoomID + "/tRoomName=" + RoomName;        }        public object DeepCopy()        {            ClassRoom r = new ClassRoom();            r.RoomID = this.RoomID;            r.RoomName = this.RoomName;            return r;        }        public object ShallowCopy()        {            //直接使用內置的淺拷貝方法返回            return this.MemberwiseClone();        }    }    class Student : IDeepCopy, IShallowCopy    {        //為了簡化,使用public 字段        public string Name;        public int Age;        //自定義類型,假設每個Student只擁有一個ClassRoom        public ClassRoom Room = new ClassRoom();        public Student()        {        }        public Student(string name, int age)        {            this.Name = name;            this.Age = age;        }        public object DeepCopy()        {            Student s = new Student();            s.Name = this.Name;            s.Age = this.Age;            s.Room = (ClassRoom)this.Room.DeepCopy();            return s;        }        public object ShallowCopy()        {            return this.MemberwiseClone();        }        public override string ToString()        {            return "Name:" + Name + "/tAge:" + Age + "/t" + Room.ToString();        }    }pastingpasting測試代碼:

Student s1 = new Student("Vivi", 28); Console.WriteLine("s1=[" + s1 + "]"); Student s2 = (Student)s1.ShallowCopy(); //Student s2 = (Student)s1.DeepCopy(); Console.WriteLine("s2=[" + s2 + "]"); //此處s2和s1內容相同 Console.WriteLine("-----------------------------"); //修改s2的內容 s2.Name = "tianyue"; s2.Age = 25; s2.Room.RoomID = 2; s2.Room.RoomName = "Room2"; Console.WriteLine("s1=[" + s1 + "]"); Console.WriteLine("s2=[" + s2 + "]"); //再次打印兩個對象以比較 Console.ReadLine();

運行結果:

a.ShallowCopys1=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]s2=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]-------------------------------------------------------------s1=[Name:Vivi   Age:28  RoomID=2        RoomName=Room2]s2=[Name:tianyue        Age:25  RoomID=2        RoomName=Room2]b.DeepCopys1=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]s2=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]-----------------------------s1=[Name:Vivi   Age:28  RoomID=1        RoomName=Room1]s2=[Name:tianyue        Age:25  RoomID=2        RoomName=Room2]        從以上結果可以看出,深拷貝時兩個對象是完全“分離”的,改變其中一個,不會影響到另一個對象;        淺拷貝時兩個對象并未完全“分離”,改變頂級對象的內容,不會對另一個對象產生影響,但改變子對象的內容,則兩個對象同時被改變。        這種差異的產生,即是取決于拷貝子對象時復制內存還是復制指針。       深拷貝為子對象重新分配了一段內存空間,并復制其中的內容;淺拷貝僅僅將指針指向原來的子對象。示意圖如下:2.淺拷貝與賦值操作        大多數面向對象語言中的賦值操作都是傳遞引用,即改變對象的指針地址,而并沒有復制內存,也沒有做任何復制操作。       由此可知,淺拷貝與賦值操作的區別是頂級對象的復制與否。當然,也有一些例外情況,比如類型定義中重載賦值操作符(assignment Operator),或者某些類型約定按值傳遞,就像C#中的結構體和枚舉類型。賦值操作示意圖如下:3.C++拷貝構造函數        與其它面向對象語言不同,C++允許用戶選擇自定義對象的傳遞方式:值傳遞和引用傳遞。在值傳遞時就要使用對象拷貝,比如說按值傳遞參數,編譯 器需要拷貝一個對象以避免原對象在函數體內被破壞。為此,C++提供了拷貝構造函數用來實現這種拷貝行為,拷貝構造函數是一種特殊的構造函數,用來完成一 些基于同一類的其它對象的構造和初始化。它唯一的參數是引用類型的,而且不可改變,通常的定義為X(const X&)。在拷貝構造函數里,用戶可以定義對象的拷貝行為是深拷貝還是淺拷貝,如果用戶沒有實現自己的拷貝構造函數,那么編譯器會提供一個默認實 現,該實現使用的是按位拷貝(bitwise copy),也即本文所說的淺拷貝。構造函數何時被調用呢?通常以下三種情況需要拷貝對象,此時拷貝構造函數將會被調用。        1.一個對象以值傳遞的方式傳入函數體        2.一個對象以值傳遞的方式從函數返回        3.一個對象需要通過另外一個對象進行初始化4.C# MemberwiseClone與ICloneable接口        和C++里的拷貝構造函數一樣,C#也為每個對象提供了淺拷貝的默認實現,不過C#里沒有拷貝構造函數,而是通過頂級類型Object里的 MemberwiseClone方法。MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。有沒有默認的深拷貝實現呢?當然是沒有,因為需要所有參與拷貝 的對象定義自己的深拷貝行為。C++里需要用戶實現拷貝構造函數,重寫默認的淺拷貝;C#則不同,C#(確切的說是.NET Framework,而非C#語言)提供了               ICloneable 接口,包含一個成員 Clone,它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。C++通過拷貝構造函數無法確定子對象實現的是深拷貝還是淺拷貝,而C#在“強制”實現淺拷貝的基礎上,提供 ICloneable 接口由用戶定義深拷貝行為,通過接口來強制約束所有參與拷貝的對象,個人覺得,這也算是一小點C#對C++的改進。 5.深拷貝策略與實現        深拷貝的要點就是確保所有參與拷貝的對象都要提供自己的深拷貝實現,不管是C++拷貝構造函數還是C#的ICloneable 接口,事實上都是一種拷貝的約定。有了事先的約定,才能約束實現上的統一,所以關鍵在于設計。        但偶爾也會在后期才想到要深拷貝,怎么辦?總不能修改所有之前的實現吧。有沒有辦法能夠通過頂級類而不關心內部的子對象直接進行深拷貝呢?能不 能搞個萬能的深拷貝方法,在想用的時候立即用,而不考慮前期的設計。這樣“大包大攬”的方法,難點在于實現時必須自動獲取子對象的信息,分別為子對象實現 深拷貝。C++里比較困難,.NET的反射機制使得實現容易一些。不過這樣的方法雖然通用,實則破壞了封裝,也不符合“每個類對自己負責”的設計原則。        基于.NET的反射機制,以前寫了一個通用的序列化方法,現在可以拿過來,先序列化,然后再反序列化回來,也即是一個深拷貝,示例代碼如下:深拷貝示例代碼:

#region ICloneable Members        /// <summary>        /// 此處的復制為深拷貝,在實現上,為了簡化,采用序列化和反序列化。        /// </summary>        /// <returns>深拷貝對象</returns>        public object Clone()        {            Student stu = new Student();            xmlStorageHelper helper = new XmlStorageHelper();            string strXml = helper.ConvertToString(this);            helper.LoadFromString(stu, strXml);   //從XML字符串來賦值            return stu;        }        #endregion


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美一性一乱一交一视频| 国产精品人人做人人爽| 欧美午夜精品在线| 米奇精品一区二区三区在线观看| 亚洲国模精品私拍| 亚洲精品动漫久久久久| 777777777亚洲妇女| 97香蕉超级碰碰久久免费的优势| 日韩a**站在线观看| 久久久av电影| 亚洲国产精品一区二区久| 精品国产91久久久久久| 亚洲女人天堂成人av在线| 91啪国产在线| 成人精品久久久| 国产精品综合不卡av| 欧美老女人xx| 亚洲男人av电影| 国产精品免费一区豆花| 欧美黑人一级爽快片淫片高清| 国外成人在线直播| 欧美大学生性色视频| 国产精品一区二区电影| 亚洲综合第一页| 日韩国产高清视频在线| 亚洲欧美在线一区二区| 欧美大片在线影院| 精品亚洲一区二区三区在线观看| 日韩av免费看| 欧美视频在线看| 91av在线免费观看视频| 国产拍精品一二三| 欧美在线观看网站| 亚洲精品日韩丝袜精品| 久久激情视频免费观看| 国产在线拍揄自揄视频不卡99| 国a精品视频大全| 欧美有码在线观看| 色天天综合狠狠色| 亚洲成人国产精品| 欧美一级高清免费| 国产欧美一区二区白浆黑人| 亚洲成**性毛茸茸| 中文字幕亚洲欧美在线| 欧美极品少妇xxxxⅹ裸体艺术| 91久久久国产精品| 色偷偷91综合久久噜噜| 久久精品国产一区二区三区| 亚洲白虎美女被爆操| 亚洲性夜色噜噜噜7777| 亚洲成人精品av| 欧美日韩国产一区在线| 精品亚洲一区二区三区四区五区| 成人国产精品一区| 欧美视频中文在线看| 国产亚洲人成网站在线观看| 日韩av中文在线| 亚洲美女免费精品视频在线观看| 最近2019年好看中文字幕视频| 成人观看高清在线观看免费| 色综合亚洲精品激情狠狠| 国产成人97精品免费看片| 国产精品九九久久久久久久| 热99精品里视频精品| 久久国产精品亚洲| 欧美精品18videos性欧美| 欧美人在线观看| 国产精品色午夜在线观看| 黄色一区二区在线观看| 欧美日韩国产va另类| 欧美日韩视频免费播放| 久久精品国产2020观看福利| 亚洲free性xxxx护士白浆| 亚洲国产精品资源| 91欧美精品午夜性色福利在线| 国产精品午夜一区二区欲梦| 色综合男人天堂| 亚洲成色www8888| 日韩精品久久久久久久玫瑰园| 久久精品免费电影| 亚洲第一网中文字幕| 久久久久久伊人| 亚洲国产成人久久综合一区| 亚洲欧美日韩国产中文专区| 91国产一区在线| 美女啪啪无遮挡免费久久网站| 国产成人精品一区二区三区| 精品久久久久久久久久ntr影视| 欧美在线一级视频| 自拍视频国产精品| 日本一区二区三区在线播放| 国产日韩精品一区二区| 欧美限制级电影在线观看| 国产精品夜间视频香蕉| 国产美女精品视频免费观看| 日韩免费精品视频| 国产亚洲视频在线| 国产精选久久久久久| 在线电影欧美日韩一区二区私密| 欧洲s码亚洲m码精品一区| 欧美—级a级欧美特级ar全黄| 亚洲精品www久久久| 国产成人av网址| 欧美日韩成人网| 中文字幕亚洲欧美日韩在线不卡| 久热国产精品视频| 亚洲欧美国产精品专区久久| 一区二区三区四区视频| 欧美夫妻性生活xx| 97在线日本国产| 欧美激情va永久在线播放| 日韩在线一区二区三区免费视频| 国产免费观看久久黄| 久久精品夜夜夜夜夜久久| 亚洲欧美制服第一页| 97香蕉久久夜色精品国产| 日韩精品中文字幕视频在线| 国产欧美精品xxxx另类| 亚洲一区二区在线播放| 国产精品久久久久久久午夜| 久久久久久一区二区三区| 亚洲精品一区二区在线| 91精品国产高清久久久久久久久| 日韩成人xxxx| 91在线直播亚洲| 亚洲国产高清高潮精品美女| 操日韩av在线电影| 欧美国产日韩一区二区在线观看| 琪琪第一精品导航| 精品自拍视频在线观看| 国产精品爽黄69天堂a| 亚洲国产精品久久久久秋霞蜜臀| 91精品久久久久久久久久久| 欧美日韩在线视频一区二区| 成人国产在线视频| 亚洲欧美日韩精品久久亚洲区| 一区二区三区美女xx视频| 成人av番号网| 国产国产精品人在线视| 久久影视免费观看| 国产精品视频最多的网站| 欧美成人全部免费| 成人黄色生活片| 欧美激情国产日韩精品一区18| 亚洲综合精品伊人久久| 懂色av一区二区三区| 久久精品小视频| 欧美日韩免费网站| 日本久久中文字幕| 亚洲国产中文字幕久久网| 一区三区二区视频| 亚洲欧洲一区二区三区久久| 欧美成人午夜免费视在线看片| 国产精品成人av性教育| 国产精品三级网站| 欧美福利视频在线| 亚洲精品丝袜日韩| 精品久久久久久久久久久久久| 激情成人在线视频| 日韩美女在线看| 97国产suv精品一区二区62| 91精品国产综合久久香蕉的用户体验| 亚洲成在人线av| 久久夜色精品国产亚洲aⅴ|