首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> ASP.NET 基礎 >> ASP.NET 基礎

.NET 深度複製與淺層複製:MemberwiseClone 與 ICloneable 實戰解析

     編輯:ASP.NET 基礎

前言:複製物件不是「指派參考」

C# 參考型別指派僅複製參考,雙方指向同一物件。若需獨立副本,必須區分淺層複製(值型別複製值、參考型別複製參考)與深度複製(遞迴建立所有參考物件的新實例)。本文以 MemberwiseClone、ICloneable 為核心,透過極簡範例徹底釐清兩者差異與實作模式。

淺層複製:MemberwiseClone


public class Content { public int Val; }

public class Cloner
{
    public Content MyContent = new Content();
    public Cloner(int v) => MyContent.Val = v;

    public object GetCopy() => MemberwiseClone(); // protected 方法,內部呼叫
}

測試:


var src = new Cloner(10);
var dst = (Cloner)src.GetCopy();
Console.WriteLine(dst.MyContent.Val); // 10
src.MyContent.Val = 15;
Console.WriteLine(dst.MyContent.Val); // 15 ← 同一 Content 實例!

結論:MemberwiseClone 只複製當前物件的欄位位元,參考型別欄位仍指向同一實例。

深度複製:實作 ICloneable


public class Cloner : ICloneable
{
    public Content MyContent = new Content();
    public Cloner(int v) => MyContent.Val = v;

    public object Clone()
    {
        // 手動建立新實例,遞迴複製參考物件
        var cloned = new Cloner(MyContent.Val); // 新 Content 隨新 Cloner 建立
        return cloned;
    }
}

測試:


var src = new Cloner(10);
var dst = (Cloner)src.Clone();
Console.WriteLine(dst.MyContent.Val); // 10
src.MyContent.Val = 15;
Console.WriteLine(dst.MyContent.Val); // 10 ← 獨立實例!

參考型別巢狀時的深度複製模式


public class Inner : ICloneable
{
    public int Data;
    public object Clone() => new Inner { Data = this.Data };
}

public class Outer : ICloneable
{
    public Inner InnerObj = new Inner();
    public object Clone()
    {
        var cloned = new Outer();
        cloned.InnerObj = (Inner)InnerObj.Clone(); // 遞迴呼叫
        return cloned;
    }
}

替代方案比較

方案優點缺點適用場景
ICloneable + 手動遞迴標準介面、完全控制樣板代碼多、易漏欄位領域模型、DTO、需精確語意
序列化反序列化 (JSON/Binary)一行代碼、自動處理巢狀效能較差、需可序列化、忽略非公有欄位快速原型、跨進程傳遞
Expression Tree / IL Emit 自動深拷貝高效能、零樣板複雜度高、需第三方庫 (FastDeepCloner 等)高頻複製、大型物件圖
Record / with 運算式 (C# 9+)不可變、語法級支援僅限 record 型別新專案、資料導向模型

最佳實務建議

  1. 優先使用不可變型別:record、readonly struct、init-only 屬性,從根源避免複製需求。
  2. 2. 必須複製時:實作 ICloneable 並明確文件化「淺/深」語意;或使用 JsonSerializer.Serialize/Deserialize 快速深拷貝(注意循環參考)。 3. 避免直接使用 MemberwiseClone 對外暴露:它是 protected 方法,語意為「淺層複製」,外部呼叫者易誤以為深度複製。 4. 效能敏感路徑:引入 FastDeepCloner 或自寫 IL 複製器,避免反射開銷。

總結

MemberwiseClone = 淺層複製(位元複製欄位),ICloneable.Clone = 您定義的語意(通常是深度複製)。理解「值型別複製值、參考型別複製參考」這一底層機制,即可在任何複製場景做出正確選擇。現代 C# 建議優先採用不可變資料模型,讓複製問題自然消失。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved