天天看點

C#中的深複制和淺複制(在C#中克隆對象)

C# 支援兩種類型:“值類型”和“引用類型”。 

值類型(Value Type)(如 char、int 和 float)、枚舉類型和結構類型。 

引用類型(Reference Type) 包括類 (Class) 類型、接口類型、委托類型和數組類型。

如何來劃分它們?

以它們在計算機記憶體中如何配置設定來劃分

值類型與引用類型的差別?

1,值類型的變量直接包含其資料,

2,引用類型的變量則存儲對象引用。

對于引用類型,兩個變量可能引用同一個對象,是以對一個變量的操作可能影響另一個變量所引用的對象。對于值類型,每個變量都有自己的資料副本,對一個變量的操作不可能影響另一個變量。

值類型隐式繼承自System.ValueType  是以不能顯示讓一個結構繼承一個類,C#不支援多繼承

堆棧(stack)是一種先進先出的資料結構,在記憶體中,變量會被配置設定在堆棧上來進行操作。

堆(heap)是用于為類型執行個體(對象)配置設定空間的記憶體區域,在堆上建立一個對象,

會将對象的位址傳給堆棧上的變量(反過來叫變量指向此對象,或者變量引用此對象)。

關于對象克隆的所設計到知識點

淺拷貝:是指将對象中的所有字段逐字複雜到一個新對象

        對值類型字段隻是簡單的拷貝一個副本到目标對象,改變目标對象中值類型字段的值不會反映到原始對象中,因為拷貝的是副本

        對引用型字段則是指拷貝他的一個引用到目标對象。改變目标對象中引用類型字段的值它将反映到原始對象中,因為拷貝的是指向堆是上的一個位址

深拷貝:深拷貝與淺拷貝不同的是對于引用字段的處理,深拷貝将會在新對象中建立一個新的對象和

        原始對象中對應字段相同(内容相同)的字段,也就是說這個引用和原始對象的引用是不同, 我們改變新

        對象中這個字段的時候是不會影響到原始對象中對應字段的内容。

淺複制: 實作淺複制需要使用Object類的MemberwiseClone方法用于建立一個淺表副本

深複制: 須實作 ICloneable接口中的Clone方法,且需要需要克隆的對象加上[Serializable]特性

namespace DeepCopy
{
    class DrawBase : System.Object, ICloneable
    {
        public List<string> listName = new List<string>();
        public string name = "old";
        public DrawBase()
        {
        }

        public object Clone()
        {
            //任選一個
            return this as object;      //引用同一個對象
            //return this.MemberwiseClone(); //淺複制
            //return new DrawBase() as object;//深複制
        }
    }


    class Program
    {
        static void Main(string[] args)
        {
            DrawBase rect = new DrawBase();
            Console.WriteLine(rect.name);
            DrawBase line =  rect.Clone() as DrawBase;
            line.name = "new";
            line.listName.Add("123");
            Console.WriteLine(rect.name);
            Console.WriteLine(rect.listName.Count);
            Console.ReadLine();
        }
    }
}      

當return this as object; 

輸出:old,new,1  

說明:方法總是引用同一個對象,是以相應的堆記憶體上的值會改變

當return this.MemberwiseClone();

輸出:old,old,1

說明:對于内部的Class的對象和數組,會Copy位址一份。[進而改變B時,A也被改變了]而對于其它内置的int/string/Enum/struct/object類型,則進行值copy。

當return new DrawBase() as object;

輸出:old,old,0

說明:完全是建立一個新對象