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

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

淺析C#深拷貝與淺拷貝

2019-11-11 05:23:24
字體:
來源:轉載
供稿:網友
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
国产精品色视频| 欧美一级淫片videoshd| 欧洲永久精品大片ww免费漫画| 国产精品视频精品视频| 久久亚洲精品网站| 亚洲女人被黑人巨大进入| 国产日韩欧美视频在线| 欧美亚州一区二区三区| 久久亚洲精品小早川怜子66| 色偷偷噜噜噜亚洲男人的天堂| 91精品视频播放| 久久人91精品久久久久久不卡| 欧美激情一级欧美精品| 91成人性视频| 国产精品久久国产精品99gif| 亚洲国产精品va在看黑人| 97人人做人人爱| 中文字幕日韩免费视频| 性亚洲最疯狂xxxx高清| 午夜精品一区二区三区在线视| 午夜精品视频网站| 日韩av在线免费观看| 成人欧美一区二区三区在线| 91亚洲国产成人久久精品网站| 国产精品高潮呻吟久久av无限| 成人在线免费观看视视频| 国内精品国产三级国产在线专| 久久久久国色av免费观看性色| 91成人天堂久久成人| 欧美疯狂做受xxxx高潮| 91久久久精品| 性欧美xxxx交| 久久久国产视频91| 中文字幕一区二区三区电影| 久久婷婷国产麻豆91天堂| 亚洲激情中文字幕| 亚洲欧美一区二区三区在线| 欧美性受xxxx白人性爽| 欧美成人激情图片网| 国产91在线高潮白浆在线观看| 日韩精品在线免费| 最近2019中文字幕mv免费看| 精品偷拍各种wc美女嘘嘘| 日本欧美中文字幕| 精品国产一区二区三区四区在线观看| 国产一区二区三区网站| 亚洲男人第一网站| 国产一级揄自揄精品视频| 亚洲成人久久久| 国产欧美一区二区三区久久人妖| 国产精品入口夜色视频大尺度| 在线观看视频99| 欧美—级a级欧美特级ar全黄| 久久久久日韩精品久久久男男| 久久99热这里只有精品国产| 国产ts一区二区| 国产精品久久国产精品99gif| 欧美激情精品久久久久久变态| 久久免费福利视频| 在线播放日韩欧美| 91日本视频在线| 久久九九精品99国产精品| 国产精品白丝jk喷水视频一区| 91av在线免费观看| 在线观看日韩视频| 欧美高清第一页| 高清欧美电影在线| 欧美精品性视频| 97欧美精品一区二区三区| 成人国产在线视频| 91九色国产社区在线观看| 成人网址在线观看| 日韩激情视频在线播放| 亚洲夜晚福利在线观看| 欧美大片网站在线观看| 日日噜噜噜夜夜爽亚洲精品| 亚洲v日韩v综合v精品v| 欧美成人免费观看| 91精品国产综合久久久久久久久| 久久久www成人免费精品张筱雨| 欧美老少配视频| 欧美巨猛xxxx猛交黑人97人| 色综合久久中文字幕综合网小说| 中文国产亚洲喷潮| 亚洲激情小视频| 欧美日韩人人澡狠狠躁视频| 久久在线精品视频| 欲色天天网综合久久| 亚洲欧美日韩在线高清直播| 色偷偷91综合久久噜噜| 色伦专区97中文字幕| 国产一区二区丝袜高跟鞋图片| 国产丝袜精品第一页| 一本一道久久a久久精品逆3p| 国产精品久久久久一区二区| 2025国产精品视频| 国产色婷婷国产综合在线理论片a| 色哟哟入口国产精品| 日韩在线观看你懂的| 精品国产91久久久久久老师| 亚洲精品按摩视频| 亚洲综合精品伊人久久| 国产精品自在线| 久久精品青青大伊人av| www国产亚洲精品久久网站| 亚洲欧美国产视频| 综合av色偷偷网| 精品国产91久久久久久| 成人午夜激情免费视频| 国产成人精品久久亚洲高清不卡| 欧美日韩在线看| 国产精品欧美风情| 国产精品成人观看视频国产奇米| 国语自产在线不卡| 国产狼人综合免费视频| 日韩精品在线观| 国产精品伦子伦免费视频| 国产一区二区三区在线观看视频| 欧美精品免费在线观看| 亚洲欧美国产精品久久久久久久| 色先锋久久影院av| 国产精选久久久久久| 亚洲三级黄色在线观看| 亚洲国产高清自拍| 亚洲成**性毛茸茸| 综合136福利视频在线| 国产一区二区丝袜高跟鞋图片| 国产99久久精品一区二区 夜夜躁日日躁| 精品国产鲁一鲁一区二区张丽| 日本午夜精品理论片a级appf发布| 91黑丝高跟在线| 亚洲国产欧美在线成人app| 亚洲性av网站| 久国内精品在线| 宅男66日本亚洲欧美视频| 日韩av成人在线观看| 日韩精品在线视频美女| 亚洲性生活视频在线观看| 色婷婷av一区二区三区在线观看| 欧美激情精品久久久久久| 伊人久久男人天堂| 日韩色av导航| 91在线观看欧美日韩| 成人免费淫片视频软件| 国产欧美日韩综合精品| 青草青草久热精品视频在线观看| 国产成人激情视频| 国产亚洲精品成人av久久ww| 三级精品视频久久久久| 98精品国产自产在线观看| 国产成人精品免费视频| 欧美性猛交xxxx免费看| 亚洲一区二区黄| 久久精品人人爽| 国产精品青青在线观看爽香蕉| 久久人人爽人人爽人人片亚洲| 日本国产一区二区三区| 欧美亚洲另类在线| 中文字幕综合在线| 91精品国产自产91精品| 久久久久久97| 在线观看亚洲区| 日本韩国在线不卡| 精品综合久久久久久97|