1. 程式人生 > >.net平臺下深拷貝和淺拷貝(實現ICloneable介面的基礎上)

.net平臺下深拷貝和淺拷貝(實現ICloneable介面的基礎上)

在.net類庫中,物件克隆廣泛存在於各種型別的實現中,凡是實現了ICloneable介面的型別都具備克隆其物件例項的能力。所以本文講述的深拷貝和淺拷貝也是在實現ICloneable介面的基礎上進行的。

基本概念:

淺拷貝:指物件的欄位被拷貝,而欄位引用的物件不會被拷貝,拷貝物件和原物件僅僅是引用名稱有所不同,但是它們共用一份實體。對任何一個物件的改變,都會影響到另外一個物件。大部分的引用型別,實現的都是淺拷貝,引用型別物件之間的賦值,就是複製一個物件引用地址的副本,而指向的物件例項仍然是同一個。

深拷貝:指物件的子段被拷貝,同時欄位引用的物件也進行了拷貝。深拷貝建立的是整個源物件的結構,拷貝物件和原物件相互獨立,不共享任何例項資料,修改一個物件不會影響到另一個物件。值型別之間的賦值操作,執行的就是深拷貝。

基本概念之參考程式碼:

-------------------------------------------------------------------------------------------------------

public class Program
{
        static void Main(string[] args)
        {
            Student s1 = new Student("li", 23);

            //淺拷貝
            Student s2 = s1;
            s2.Age = 27;
            s1.ShowInfo();//li's age is 27

            //深拷貝
            int i = 12;
            int j = i;
            j = 22;
            Console.WriteLine(i);//12

            Console.Read();
        }
}

public   class Student
{
        public string Name;
        public int Age;

        public Student(string name, int age)
        {
            Name = name;
            Age = age;
        }

        public void ShowInfo()
        {
            Console.WriteLine("{0}'s age is {1}", Name, Age);
        }
 }

--------------------------------------------------------------------------------------------------------

分析:

在上例中,例項s2對s1進行了淺拷貝,對s2中的Age欄位進行更改,繼而影響例項s1中的Age欄位。

深拷貝中,僅僅是值型別間簡單的賦值,對“j”做出的更改不會更改“i”的值。

注:上述例項中的“淺拷貝”和“深拷貝”其實都和淺拷貝、深拷貝沒有關係(因為它們都沒有實現Clone),僅僅是為了說明淺拷貝和深拷貝的效果。

深淺拷貝的實現:

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

MemberwiseClone:建立一個淺表副本。過程是建立一個新物件,然後將當前物件的非靜態欄位複製到該新物件。如果欄位是值型別,則對該欄位執行逐位複製,如果欄位是引用型別,則複製引用但不復制引用物件。

public    class Program
    {
        static void Main(string[] args)
        {
            ClassA ca = new ClassA();
            ca.value = 88;
            ClassA ca2 = new ClassA();
            ca2 = (ClassA)ca.Clone();
            ca2.value = 99;
            Console.WriteLine(ca.value + "-----" + ca2.value);//88---99

            ClassB cb = new ClassB();
            cb.Member.value = 13;

            ClassB cb2 = (ClassB)cb.Clone();
            cb2.Member.value = 7;
            Console.WriteLine(cb.Member.value.ToString() + "------" + cb2.Member.value.ToString());//淺拷貝:7---7      深拷貝:13----7           

            Console.Read();
        }
    }

    public class ClassA : ICloneable
    {
        public int value = 0;

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

    public class ClassB : ICloneable
    {
        public ClassA Member = new ClassA();

        public object Clone()
        { 
            //淺拷貝
            return this.MemberwiseClone();

            //深拷貝
            ClassB obj = new ClassB();
            obj.Member = (ClassA)Member.Clone();
            return obj;
        }
    }