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

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

淺析C#深拷貝與淺拷貝

2019-11-11 05:21:53
字體:
來源:轉載
供稿:網友
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
亚洲一区美女视频在线观看免费| 亚洲精品久久久一区二区三区| 在线一区二区日韩| 欧美小视频在线观看| 精品视频在线观看日韩| 亚洲石原莉奈一区二区在线观看| 国产精品成人品| 欧美成人精品三级在线观看| 欧美激情啊啊啊| 高清亚洲成在人网站天堂| 欧美在线精品免播放器视频| 精品国产91久久久久久老师| 日韩美女激情视频| 91理论片午午论夜理片久久| 日韩国产欧美区| 亚洲中国色老太| 国产福利成人在线| 久久天天躁狠狠躁老女人| 亚洲国产精品久久久久秋霞蜜臀| 亚洲美女av在线| 午夜精品久久久99热福利| 夜夜嗨av一区二区三区四区| 91精品综合视频| 久久久av一区| 久久91亚洲精品中文字幕奶水| 亚洲天堂久久av| 麻豆成人在线看| 欧美日韩亚洲网| 亚洲国产又黄又爽女人高潮的| 亚洲精品天天看| 久久人人看视频| 国产精品久久久久影院日本| 91在线观看免费高清| 欧美在线一区二区视频| 日韩欧美国产视频| 国产精品91久久久| 日韩精品在线私人| 尤物九九久久国产精品的分类| 国内精品一区二区三区| 亚洲欧美另类在线观看| 色噜噜狠狠狠综合曰曰曰| 久久精品国产清自在天天线| 国产精品一区电影| 97av在线播放| 久久国内精品一国内精品| 97香蕉超级碰碰久久免费的优势| 亚洲а∨天堂久久精品9966| 91在线精品播放| 成人在线国产精品| 日韩av在线网址| 日韩av黄色在线观看| 中文字幕欧美精品日韩中文字幕| 成人在线精品视频| 国产美女直播视频一区| 欧美最近摘花xxxx摘花| 色系列之999| 国产精品久久久久久五月尺| 亚洲第一视频网站| 国产精品视频一区二区高潮| 91丝袜美腿美女视频网站| 欧美视频第一页| 亚洲精品久久久久久久久久久久| 最近更新的2019中文字幕| 疯狂欧美牲乱大交777| 国产一区二区在线播放| 亚洲香蕉伊综合在人在线视看| 国产成人黄色av| 欧美成人免费小视频| 亚洲a中文字幕| 欧美性受xxx| 国产一区二区三区在线| 亚洲大尺度美女在线| 国产精国产精品| 欧美在线观看视频| 亚洲深夜福利在线| 欧美风情在线观看| 午夜精品久久久久久久白皮肤| 亚洲专区在线视频| 久久在线免费观看视频| 欧美日韩亚洲视频一区| 日本久久久久久久| 久久久免费观看视频| 日韩电影在线观看中文字幕| 最近2019好看的中文字幕免费| 亚洲一区二区三区在线视频| 91久久精品日日躁夜夜躁国产| 欧美日韩中文字幕在线| 中日韩午夜理伦电影免费| 日日狠狠久久偷偷四色综合免费| 日韩电影大全免费观看2023年上| 国产一区二区三区直播精品电影| 菠萝蜜影院一区二区免费| 日韩在线播放av| 欧美性感美女h网站在线观看免费| 亚洲欧美精品一区二区| 亚洲a成v人在线观看| 成人免费观看网址| 91av在线视频观看| 久久久久久久久久久91| 欧美中文字幕精品| 91在线高清免费观看| 欧美巨乳在线观看| 国产午夜精品视频| 亚洲精品国产精品国自产观看浪潮| 中文字幕亚洲图片| 日韩中文字幕在线视频| 欧美一区二区三区艳史| 91精品国产91久久久久久吃药| 欧美激情一区二区三级高清视频| 欧美日韩亚洲视频| 欧美激情xxxxx| 在线观看亚洲视频| 欧美三级xxx| 国产成人精品视频| 日韩电影中文字幕一区| 91爱爱小视频k| 日韩视频在线一区| 国产精品久久久久久久久久尿| 国产欧美精品一区二区| 欧美一乱一性一交一视频| 亚洲天堂av电影| 亚洲国产精品va在线| 日韩经典一区二区三区| 91精品国产高清| 国产日韩欧美日韩| 亚洲理论在线a中文字幕| 一区二区av在线| 亚洲视频网站在线观看| 91久久久在线| 久久久久亚洲精品| 一区二区三区动漫| 亚洲天堂av在线免费| 欧美一区二区三区免费观看| 亚洲成在人线av| 欧美性xxxxx极品娇小| 欧美成人剧情片在线观看| 国产日韩亚洲欧美| 综合网日日天干夜夜久久| 久久国产精品视频| 亚洲第一av网站| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产狼人综合免费视频| 日韩中文在线不卡| 日韩av不卡在线| 国产精品专区h在线观看| 精品国产一区二区三区久久狼黑人| 国产三级精品网站| 亚洲成人久久久| 伊人久久精品视频| 亚洲综合日韩中文字幕v在线| 欧美天天综合色影久久精品| 欧美中文字幕精品| 美女啪啪无遮挡免费久久网站| 久久中文久久字幕| 久久久久99精品久久久久| 91亚洲精品一区二区| 中文字幕日韩欧美在线| 欧美激情国产日韩精品一区18| 亚洲精品久久久久中文字幕二区| 国产精品久久久久久久av大片| 精品国内产的精品视频在线观看| 国产成人精品久久二区二区| 亚洲一区av在线播放| 91免费版网站入口|