.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;
}
}