在 .Net Framework中,物件類型可分為 ValueType 及 Reference Type 兩種類型,也就讓物件的複製分為「淺複製(Shallow Copy)」及「深複製(Deep Copy)」兩種。
淺複製
將原有物件的欄位依照其類型作相對應的處理,Value Type欄位複製其數值到另一個空間,Reference Type欄位則是複製其參考到另一個空間,因此此兩物件的Refetence Type 都是參考到同一instance。
深複製
ValueType與「淺複製」相同,主要差異是「深複製」的Reference Type欄位會產生新的instance,所以其倆欄位是參考到不同instance的。
程式範例
直接看程式比較容易了解。首先是定義Studernt這個class。Student有兩個欄位,Number是 Value Type, Name是 Reference Type
public class Student
{
public Student(int num, string name)
{
Number = num;
Name = new StringBuilder(name);
}
public StringBuilder Name { get; set; }
public int Number { get; set; }
}
然後程式會產生一個叫 brian的 Strudent物件,然後分別呼叫「淺複製」與「深複製」此兩個方法來產生新的複製物件。接著更改一開始產生的brian欄位內容,最後再去觀察複製的兩物件內容。
Student brian = new Student(0, "Brian");
Student shallowBrian = brian.ShallowCopy();
Student deepBrian = brian.DeepCopy();
Console.WriteLine("Before Change: {0}", brian);
brian.Number = 1;
brian.Name.Append(" Tseng");
Console.WriteLine("After Change: {0}", brian);
Console.WriteLine();
Console.WriteLine("Shallow Copy: {0}", shallowBrian);
Console.WriteLine("Deep Copy: {0}", deepBrian);
Console.ReadKey();
執行結果:
我們先來觀察「淺複製」的shallowBrian,當原先物件內容被改變後,Number沒有變動,而Name卻跟著變動了。所以我們可以知道,Brian物件跟shallowBrian的Name都是參考到同一個instance,而ValueType的Number則是各自獨立的。
而「深複製」的deepBrian則不管是Number或是Name都沒跟著變動,也就表示它們是互相獨立的,彼此都是參考到自己的instance。
方法實作
public Student ShallowCopy()
{
return MemberwiseClone() as Student;
}
public Student DeepCopy()
{
return new Student(Number, Name.ToString());
}
「淺複製」呼叫 Object.MemberwiseClone()這個方法就能實作,而「深複製」則是產生另一個物件回去。
參考資料