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

C# 內存管理深度解析(六):引用類型拷貝陷阱與 ICloneable 解決方案

     編輯:關於C語言

現象復現


class Shoe { public string Color; }
class Dude
{
    public string Name;
    public Shoe LeftShoe, RightShoe;
    public Dude CopyDude() => new Dude { Name = Name, LeftShoe = LeftShoe, RightShoe = RightShoe };
}

// 測試
Dude bill = new Dude { Name = "Bill", LeftShoe = new Shoe { Color = "Blue" }, RightShoe = new Shoe { Color = "Blue" } };
Dude ted = bill.CopyDude();
ted.Name = "Ted";
ted.LeftShoe.Color = ted.RightShoe.Color = "Red";

Console.WriteLine(bill); // 錯誤輸出:Bill: Red / Red  ← 共享 Shoe 實例!
Console.WriteLine(ted);  // Ted: Red / Red

根因:淺拷貝

LeftShoe = LeftShoe 僅複製引用(指針),bill 與 ted 指向同一 Shoe 對象。

解決方案:ICloneable 深拷貝


class Shoe : ICloneable
{
    public string Color;
    public object Clone() => new Shoe { Color = (string)Color.Clone() };
}

class Dude
{
    public string Name;
    public Shoe LeftShoe, RightShoe;
    public Dude CopyDude() => new Dude
    {
        Name = Name,
        LeftShoe = (Shoe)LeftShoe.Clone(),
        RightShoe = (Shoe)RightShoe.Clone()
    };
}

// 重新測試 → 輸出正確:Bill: Blue/Blue, Ted: Red/Red

進階:在 CopyDude 中直接調用 Clone

無需修改 Dude 實現 ICloneable,只需約定子對象支持 Clone()。

字符串 Clone 特殊性

  • string.Clone() 返回自身(不可變),無額外分配。
  • 因此 (string)Color.Clone() 安全高效。

包裝實體模式

將值類型包裝為引用類型(class MyInt { public int Value; })可實現引用語義傳遞,但會增加堆分配與 GC 壓力,僅在必要時使用(如需在多處共享可變數值)。

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