[C#] 複製物件的方式比較

在 .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()這個方法就能實作,而「深複製」則是產生另一個物件回去。

參考資料

Object.MemberwiseClone 方法

[C#.NET] 淺複製與深複製