淺復制(Shallow Copy)與深復制(Deep Copy)


復制:對象的復制是生成一個與指定對象完全一樣的新對象,實現的方式根據定義可以知道,新建一個類型相同的對象,然后復制原對象的每一個成員和字段。

 淺復制:

    class Program
    {
        static void Main(string[] args)
        {
            ClassA A = new ClassA();
            CloneObj clone = new CloneObj();
            ClassA newA= clone.CloneA(A);
        }
    }

    public class ClassA
    {
        public Int32 AValue = 100;
    }

    public class ClassB
    {
        public Int32 BValue = 200;
    }

    public class CloneObj
    {
        public ClassA CloneA(ClassA obj)
        {
            ClassA newAobj = new ClassA();
            newAobj.AValue = obj.AValue;
            return newAobj;
        }
    }

上面的CloneObj的CloneA方法就是一個淺復制ClassA對象,修改代碼:

    class Program
    {
        static void Main(string[] args)
        {
            ClassA A = new ClassA();
            CloneObj clone = new CloneObj();
            ClassA newA= clone.CloneA(A);
        }
    }

    public class ClassA
    {
        public Int32 AValue = 100;
        public ClassB objB;
        public ClassA()
        {
            objB = new ClassB();
        }
    }

    public class ClassB
    {
        public Int32 BValue = 200;
    }

    public class CloneObj
    {
        public ClassA CloneA(ClassA obj)
        {
            ClassA newAobj = new ClassA();
            newAobj.AValue = obj.AValue;
            newAobj.objB = obj.objB;
            return newAobj;
        }
    }

這里ClassA里面包含了引用類型的ClassB對象,這里復制的ClassA對象,如下圖:

上面這種方式就是“淺復制(Shallow Copy)”,這里可以在調試時測試下,看看A里面objB的地址和通過復制方法出來的newA的objB的地址:

地址完全一樣

淺復制是.NET默認的對象復制方式,Object類提供的Memberwise方法淺復制一個對象。實現深復制,也就是上面的圖中,不是共用一個ClassB對象,而是完全創建一個新的ClassB對象。這需要實現ICloneable接口.如下:

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            ClassA A = new ClassA();
            CloneObj clone=new CloneObj();
            ClassA newA = clone.CloneA(A);

        }
    }

    public class ClassA:ICloneable
    {
        public Int32 AValue = 100;
        public ClassB objB;
        public ClassA()
        {
            objB = new ClassB();
        }

        object ICloneable.Clone()
        {
            ClassA objA = new ClassA();
            objA.AValue = this.AValue;
            objA.objB = (this.objB as ICloneable).Clone() as ClassB;
            return objA;
        }
    }

    public class ClassB:ICloneable
    {
        public Int32 BValue = 200;

        object ICloneable.Clone()
        {
            ClassB objB = new ClassB();
            objB.BValue = this.BValue;
            return objB;
        }
    }

    public class CloneObj
    {
        public ClassA CloneA(ClassA obj)
        {
            //ClassA newAobj = new ClassA();
            //newAobj.AValue = obj.AValue;
            //newAobj.objB = obj.objB;
            ClassA newAobj = (obj as ICloneable).Clone() as ClassA;
            return newAobj;
        }
    }

}

測試結果如圖:

這里完成了深復制

對象序列化

對象復制比較簡單的方式是序列化,將類標記為[Serializable]。對象序列化主要解決的是對象狀態的保存問題,這里所說的“對象狀態”是指某一時刻對象擁有的字段值的集合。

對象的序列化:將一個內存的對象保存到流中,並在需要時從流中讀取數據重建對象的過程稱為“對象序列化”和“反序列化”

流:代表一連串有順序的二進制數據。

利用序列化進行對象的復制——深復制

    [Serializable]
    class MyClass
    {
        public int Index = 1;
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyClass obj = new MyClass();
            //創建一個內存流對象
            using (MemoryStream ms = new MemoryStream())
            {
                IFormatter formator = new BinaryFormatter();
                formator.Serialize(ms, obj);  //將對象序列化到內存流中 

                //克隆100個對象
                for (int i = 0; i < 100; i++)
                {
                    ms.Seek(0, SeekOrigin.Begin);//回到流的開頭
                    obj = (formator.Deserialize(ms) as MyClass); //反序列化對象
                    obj.Index += i;   //設置對象字段
                    Console.WriteLine("對象{0}已創建。", obj.Index);
                }
            }
            Console.ReadKey();
        }
    }

原理是將對象序列化到流中,然后從流中創建對象(批量),從而實現了深復制。

讀書筆記《.NET4.0面向對象編程漫談》作者:金旭亮老師


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM