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

首頁 > 編程 > C# > 正文

淺拷貝和深拷貝深入理解(shallow copy VS deep copy)

2020-01-24 02:53:24
字體:
來源:轉載
供稿:網友

引言
C#中有兩種類型變量,一種 是值類型變量,一種是引用類型變量,對于值類型變量,深拷貝和前拷貝都是通過賦值操作符號(=)實現,其效果一致,將對象中的值類型的字段拷貝到新的對象中.這個很容易理解。 本文重點討論引用類型變量的拷貝機制和實現。

C#中引用類型對象的copy操作有兩種:

•淺拷貝(影子克隆/shallow copy):只復制對象的值類型字段,對象的引用類型,仍屬于原來的引用.
•深拷貝(深度克隆):不僅復制對象的值類型字段,同時也復制原對象中的對象.就是說完全是新對象產生的.

淺拷貝和深拷貝之間的區別:淺拷貝是指將對象中的數值類型的字段拷貝到新的對象中,而對象中的引用型字段則指復制它的一個引用到目標對象。

注意:string類型有點特殊,對于淺拷貝,類值類型對象進行處理。

淺拷貝的實現
1.使用Object類MemberwiseClone實現
MemberwiseClone:創建當前 Object 的淺表副本。
MemberwiseClone 方法創建一個淺表副本,方法是創建一個新對象,然后將當前對象的非靜態字段復制到該新對象。如果字段是值類型的,則對該字段執行逐位復制。如果字段是引用類型,則復制引用但不復制引用的對象;因此,原始對象及其復本引用同一對象。

代碼實現如下:

復制代碼 代碼如下:

public class Person
    {
        public int Age { get; set; }
        public string Address { get; set; }
        public Name Name { get; set; }

        public object Clone()
        {
           return   this.MemberwiseClone();   
        }

       
    }


    public class Name
    {
        public Name(string frisName,string lastName)
        {
            FristName = frisName;
            LastName = lastName;
        }
        public string FristName { get; set; }
        public string LastName { get; set; }
    }


2.賦值操作(=)VS使用Object類MemberwiseClone實現
對于引用類型的變量,我們有種誤解,認為賦值操作就是淺拷貝一種,其實不然,兩者有區別。

1.淺拷貝(shallow copy)對于引用類型對象中的值類型字段進行了逐位復制。賦值運算符只是把源對象的引用賦值給目的對象,兩者引用同一個對象。

2.淺拷貝后的對象的值類型字段更改不會反映到源對象,而賦值運算后的對象的值類型字段更改會反映到源對象

代碼實現如下:

復制代碼 代碼如下:

public class Person
    {
        public int Age { get; set; }
        public string Address { get; set; }
        public Name Name { get; set; }
    }


    public class Name
    {
        public Name(string frisName,string lastName)
        {
            FristName = frisName;
            LastName = lastName;
        }
        public string FristName { get; set; }
        public string LastName { get; set; }
    }


深拷貝實現
相對于淺拷貝,是指依照源對象為原型,創建一個新對象,將當前對象的所有字段進行執行逐位復制并支持遞歸,不管是是值類型還是引用類型,不管是靜態字段還是非靜態字段。
在C#中,我們們有三種方法實現深拷貝

1.實現ICloneable接口,自定義拷貝功能。

ICloneable 接口,支持克隆,即用與現有實例相同的值創建類的新實例。

ICloneable 接口包含一個成員 Clone,它用于支持除 MemberwiseClone 所提供的克隆之外的克隆。Clone 既可作為深層副本實現,也可作為淺表副本實現。在深層副本中,所有的對象都是重復的;而在淺表副本中,只有頂級對象是重復的,并且頂級以下的對象包含引用。 結果克隆必須與原始實例具有相同的類型或是原始實例的兼容類型。

代碼實現如下:

復制代碼 代碼如下:

 public class Person:ICloneable
    {
        public int Age { get; set; }
        public string Address { get; set; }
        public Name Name { get; set; }

        public object Clone()
        {
            Person tem = new Person();
            tem.Address = this.Address;
            tem.Age = this.Age;

            tem.Name = new Name(this.Name.FristName, this.Name.LastName);

            return tem;
        }
    }


    public class Name
    {
        public Name(string frisName, string lastName)
        {
            FristName = frisName;
            LastName = lastName;
        }
        public string FristName { get; set; }
        public string LastName { get; set; }
    }


大家可以看到,Person類繼承了接口ICloneable并手動實現了其Clone方法,這是個簡單的類,試想一下,如果你的類有成千上萬個引用類型成員(當然太夸張,幾十個還是有的),這是不是份很恐怖的勞力活?

2.序列化/反序列化類實現

不知道你有沒有注意到DataSet對象,對于他提供的兩個方法:

DataSet.Clone 方法,復制 DataSet 的結構,包括所有 DataTable 架構、關系和約束。不要復制任何數據。

新 DataSet,其架構與當前 DataSet 的架構相同,但是不包含任何數據。注意 如果已創建這些類的子類,則復本也將屬于相同的子類。

DataSet.Copy 方法復制該 DataSet 的結構和數據.

新的 DataSet,具有與該 DataSet 相同的結構(表架構、關系和約束)和數據。注意如果已創建這些類的子類,則副本也將屬于相同的子類。

好像既不是淺拷貝,又不是深拷貝,是不是很失望?但是兩個結合起來不是我們要的深拷貝嗎?看看DataSet的實現,注意序列化接口:ISerializable

序列化是將對象或對象圖形轉換為線性字節序列,以存儲或傳輸到另一個位置的過程。反序列化是接受存儲的信息并利用它重新創建對象的過程。

通過 ISerializable 接口,類可以執行其自己的序列化行為。

轉換為線性字節序列后并利用其重新創建對象的過程是不是和我們的深拷貝的語意“逐位復制”很相像?

代碼實現如下:

復制代碼 代碼如下:

[Serializable]
    public class Person : ICloneable
    {
        public int Age { get; set; }
        public string Address { get; set; }
        public Name Name { get; set; }

        public object Clone()
        {
            using (MemoryStream ms = new MemoryStream(1000))
            {
                object CloneObject;

                BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.Clone));
                bf.Serialize(ms, this);

                ms.Seek(0, SeekOrigin.Begin);

                // 反序列化至另一個對象(即創建了一個原對象的深表副本)
                CloneObject = bf.Deserialize(ms);

                // 關閉流
                ms.Close();
                return CloneObject;
            }
        }
    }


    [Serializable]
    public class Name
    {
        public Name(string frisName, string lastName)
        {
            FristName = frisName;
            LastName = lastName;
        }
        public string FristName { get; set; }
        public string LastName { get; set; }
    }

}


注意:通過序列化和反序列化實現深拷貝,其和其字段類型必須標記為可序列化類型,既添加特性(Attribute)[Serializable]。

3.通過反射實現
通過序列化/反序列化方式我們能比較流暢的實現深拷貝,但是涉及到IO操作,托管的的環境中,IO操作比較消耗資源。 能不能有更優雅的解決方案。CreateInstance,對,利用反射特性。這個方法大家可以參考這篇博客:http://rubenhak.com/?p=70 文章反射類的Attribute,利用Activator.CreateInstance New一個類出來(有點像DataSet.Clone先獲得架構),然后利用PropertyInfo的SetValue和GetValue方法,遍歷的方式進行值填充。

代碼實現如下:

復制代碼 代碼如下:

public class Person
{
    private List<Person> _friends = new List<Person>();

    public string Firstname { get; set; }
    public string Lastname { get; set; }

    [Cloneable(CloneableState.Exclude)]
    [Cloneable(CloneableState.Include, "Friends")]
    public List<Person> Friends { get { return _friends; } }

    [Cloneable(CloneableState.Exclude)]
    public PersonManager Manager { get; set; }
}


C#為什么要設計深拷貝和淺拷貝?
這個我也一直也找不到一個合適的答案,希望有人來討論下!點擊下載代碼

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
午夜精品视频网站| 亲子乱一区二区三区电影| 日韩av123| 国产精品pans私拍| 在线免费看av不卡| 色偷偷91综合久久噜噜| 国产一区二区丝袜| 在线精品视频视频中文字幕| 精品国产依人香蕉在线精品| 国产一区二区三区三区在线观看| 色婷婷av一区二区三区久久| 欧美最猛性xxxx| 国产精品精品一区二区三区午夜版| 欧美最猛性xxxxx(亚洲精品)| 亚洲三级黄色在线观看| 亚洲欧美在线免费观看| 久久99热精品| 成人免费在线网址| 久久久久久12| 九九热精品视频在线播放| 精品国产1区2区| 日本欧美一二三区| 欧美亚洲成人精品| 国产成人jvid在线播放| 日韩av在线直播| 一区二区福利视频| 中文字幕综合一区| 91影视免费在线观看| 欧美中文在线视频| 国产香蕉97碰碰久久人人| 亚洲国产日韩欧美综合久久| 国产成人一区二区| 日韩精品一二三四区| 国产精品成人播放| 亚洲欧美国产精品va在线观看| 91精品国产色综合久久不卡98| 日本一区二区三区在线播放| 国产91精品黑色丝袜高跟鞋| 97久久久免费福利网址| 精品久久久91| www.日韩.com| 国产精品视频1区| 91精品国产高清久久久久久久久| 久久久久久久激情视频| 日韩经典中文字幕在线观看| 色悠悠久久88| 亚洲美女动态图120秒| 粉嫩av一区二区三区免费野| 九九热精品视频国产| 亚洲欧美国产制服动漫| 亚洲色图13p| 国产婷婷97碰碰久久人人蜜臀| 国产69精品久久久久9| 海角国产乱辈乱精品视频| 欧美激情国产日韩精品一区18| 92裸体在线视频网站| 日韩精品视频在线观看免费| 美女999久久久精品视频| 亚洲va久久久噜噜噜久久天堂| 欧美日韩成人在线播放| 日本欧美国产在线| 蜜臀久久99精品久久久久久宅男| 欧美在线视频免费观看| 欧美高清视频在线观看| 国产精品99一区| 日本久久久a级免费| 欧美一区二区影院| 一本色道久久88综合亚洲精品ⅰ| 亚洲欧洲成视频免费观看| 91精品视频在线| 国a精品视频大全| 成人精品视频久久久久| 亚洲美女av黄| 日韩在线观看电影| 欧美性xxxxx极品娇小| 国产色婷婷国产综合在线理论片a| 九九久久精品一区| 成人免费福利视频| 国产视频亚洲视频| 97在线视频免费| 久久亚洲综合国产精品99麻豆精品福利| 久久久视频在线| 国产精品免费福利| 欧美二区乱c黑人| 国产精品自产拍在线观看中文| 欧美日韩国产综合视频在线观看中文| www.日韩不卡电影av| 97热精品视频官网| 亚洲女人初尝黑人巨大| 欧美有码在线观看视频| 久久精品久久久久久| 欧洲s码亚洲m码精品一区| 91精品免费久久久久久久久| 亚洲一区二区在线播放| 成人深夜直播免费观看| 久久这里只有精品99| 精品电影在线观看| 亚洲毛片一区二区| xxav国产精品美女主播| 日韩av资源在线播放| 中文字幕亚洲综合久久筱田步美| 久久久人成影片一区二区三区观看| 粉嫩老牛aⅴ一区二区三区| 亚洲精品电影在线观看| 国产91对白在线播放| 日韩中文在线中文网三级| 午夜精品一区二区三区在线播放| 久久久亚洲国产天美传媒修理工| 亚洲娇小xxxx欧美娇小| 国产91在线高潮白浆在线观看| 午夜精品一区二区三区在线视| 成人在线观看视频网站| 国产在线视频欧美| 国产精品第100页| 色阁综合伊人av| 正在播放亚洲1区| 国产一区二区三区在线播放免费观看| 色综合导航网站| 国产精品∨欧美精品v日韩精品| 亚洲**2019国产| 欧美午夜精品久久久久久人妖| 91高清视频免费| 亚洲免费成人av电影| 久久亚洲精品一区二区| 国产一区二区香蕉| 国产视频久久久久久久| 国产精品久久久久久五月尺| 成人激情视频小说免费下载| 欧美国产日韩xxxxx| 亚洲最大福利网站| 欧美大片在线看| 成人黄色片网站| www.国产精品一二区| 91精品国产乱码久久久久久蜜臀| 久久精品这里热有精品| 亚洲性日韩精品一区二区| 欧美黑人巨大xxx极品| 色噜噜狠狠狠综合曰曰曰| 久久精品国产亚洲一区二区| 91性高湖久久久久久久久_久久99| 国产91精品久| 青青草精品毛片| 热久久99这里有精品| 久久亚洲精品视频| 久久久噜噜噜久久久| 欧美日韩在线观看视频| 国产精品日韩欧美| 久久99精品久久久久久青青91| 久久久久久久久久国产精品| 91精品国产乱码久久久久久蜜臀| 亚洲国产精品资源| 久久久久九九九九| 一区二区日韩精品| 中文字幕日韩高清| 日韩中文字幕在线免费观看| 欧美成人黑人xx视频免费观看| 成人黄色免费网站在线观看| 久久久999成人| 国产精品91久久久久久| 亚洲国产又黄又爽女人高潮的| 国产精品三级美女白浆呻吟| 国产精品精品国产| 91影视免费在线观看| 亚洲精品网站在线播放gif|