深拷貝與淺拷貝是 C# 進階面試必考題,也是設計高效能、正確資料結構的關鍵知識。本文系統整理概念定義、實作機制、程式碼範例與執行結果分析,建立完整認知框架。
| 類型 | 定義 | 值型別處理 | 參考型別處理 | 記憶體關係 |
|---|---|---|---|---|
| 淺拷貝 (Shallow Copy) | 僅複製物件欄位值,參考型別欄位複製「參考位址」 | 逐位元複製 (Bitwise copy) | 複製參考,新舊物件指向同一個實體物件 | 共享參考型別資料 |
| 深拷貝 (Deep Copy) | 完全建立新物件,包含遞迴複製所有參考型別欄位指向的實體 | 逐位元複製 | 遞迴建立新的實體物件並複製內容 | 完全獨立,互不影響 |
int[] arr1 = { 1, 2, 3 };
int[] arr2 = arr1; // 參考賦值 (非拷貝)
int[] arr3 = (int[])arr1.Clone(); // 淺拷貝 = 深拷貝 (值型別陣列)
arr3[0] = 99; // arr1[0] 仍為 1
值型別陣列 Clone()、CopyTo()、Array.Copy() 皆產生獨立副本。
| 方法 | 類別 | 行為 | 適用場景 |
|---|---|---|---|
MemberwiseClone() | Object | 建立淺副本:值型別複製、參考型別複製參考 | 淺拷貝基礎實作 |
ICloneable.Clone() | 介面 | 語意由實作者定義,通常實作深拷貝 | 公開深拷貝契約 |
public class ValueTypeCopy
{
public void MethodShallowCopyDirectly()
{
int[] arr1 = { 0, 1, 2, 3 };
int[] arr2 = arr1; // 參考賦值,非拷貝
arr2[0] = 8;
// arr1[0] 變為 8 → 同一陣列實體
}
public void MethodShallowCopyArrayClone()
{
int[] arr1 = { 0, 1, 2, 3 };
int[] arr2 = (int[])arr1.Clone(); // 新陣列,值複製
arr2[0] = 8; // arr1[0] 仍為 0
}
// CopyTo、Array.Copy 同理產生獨立值型別陣列
}
// 淺拷貝:複製參考
string[] src = { "A", "B", "C" };
string[] shallow = src; // 或 src.Clone()
shallow[0] = "X"; // src[0] 也變 "X" → 共享字串物件 (不可變特性掩蓋此問題)
// 真正驗證需用可變參考型別
class Data { public int Value; }
Data[] src = { new Data{Value=1}, new Data{Value=2} };
Data[] shallow = (Data[])src.Clone();
shallow[0].Value = 99; // src[0].Value 也變 99 → 共享 Data 實體
// 深拷貝:逐項建立新實體
Data[] deep = new Data[src.Length];
for (int i = 0; i < src.Length; i++)
deep[i] = new Data { Value = src[i].Value };
deep[0].Value = 88; // src[0].Value 仍為 1 → 完全獨立
// 深拷貝實作
public class CarDeepClone : ICloneable
{
public string Name { get; set; }
public int Price { get; set; }
public Engine Engine { get; set; } // 參考型別欄位
public object Clone()
{
return new CarDeepClone
{
Name = this.Name,
Price = this.Price,
Engine = this.Engine != null ? (Engine)this.Engine.Clone() : null // 遞迴深拷貝
};
}
}
// 淺拷貝實作
public class CarShallowClone : ICloneable
{
public string Name { get; set; }
public int Price { get; set; }
public Engine Engine { get; set; }
public object Clone()
{
return this.MemberwiseClone(); // 僅複製參考
}
}
// 深拷貝測試
var car1 = new CarDeepClone { Name = "Benz", Price = 700, Engine = new Engine { HP = 300 } };
var car2 = (CarDeepClone)car1.Clone();
car2.Name = "BMW";
car2.Engine.HP = 400;
// car1.Name 仍為 "Benz", car1.Engine.HP 仍為 300 → 完全獨立
// 淺拷貝測試
var car3 = new CarShallowClone { Name = "Audi", Price = 500, Engine = new Engine { HP = 250 } };
var car4 = (CarShallowClone)car3.Clone();
car4.Name = "VW";
car4.Engine.HP = 350;
// car3.Name 仍為 "Audi" (string 不可變), 但 car3.Engine.HP 變為 350 → 共享 Engine 實體

Clone()、CopyTo()、Array.Copy() 皆為深拷貝效果Clone():淺拷貝,元素參考共享MemberwiseClone():淺拷貝,參考型別欄位共享實體Clone() 配合 new 建構:深拷貝,完全獨立public static T DeepClone<T>(T obj) where T : class
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T)formatter.Deserialize(ms);
}
}
// 需標記 [Serializable],效能較差但零程式碼維護
readonly / init (C# 9+)with 運算子 / 方法回傳新物件)| 方法 | 效能 | 適用性 |
|---|---|---|
| MemberwiseClone + 手動深拷貝參考欄位 | ★★★★★ | 高效能、固定結構 |
| 序列化/反序列化 | ★★☆☆☆ | 複雜物件圖、跨進程 |
| JSON 循環序列化 | ★★★☆☆ | POCO、無循環參考 |
| Expression Tree 編譯複製 | ★★★★☆ | 高頻呼叫、動態型別 |
掌握深淺拷貝本質,依據物件圖複雜度、效能需求、維護成本選擇適當策略,是 .NET 開發者進階的關鍵里程碑。