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

C# 內存管理深度解析(五):值類型與引用類型的拷貝語義

     編輯:關於C語言

核心現象

當結構體 Shoe 作為類 Dude 的字段時:

  • 值類型:拷貝 Dude 會完整複製 Shoe 數據,修改副本不影響原對象。
  • 引用類型:拷貝 Dude 僅複製引用,副本與原對象共享同一 Shoe 實例,修改會相互影響。

代碼對比

值類型版本(結構體)


public struct Shoe { public string Color; }

public class Dude
{
    public string Name;
    public Shoe LeftShoe, RightShoe;

    public Dude CopyDude()
    {
        return new Dude
        {
            Name = this.Name,
            LeftShoe = this.LeftShoe,   // 值拷貝
            RightShoe = this.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";

// 輸出:
// Bill : Blue / Blue
// Ted  : Red  / Red   ← 互不影響

引用類型版本(類)


public class Shoe { public string Color; } // 改為 class

// 相同測試代碼
// 輸出:
// Bill : Red / Red   ← 被意外修改!
// Ted  : Red / Red

根因分析

解決方案:實現 ICloneable


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

public class Dude : ICloneable
{
    public string Name;
    public Shoe LeftShoe, RightShoe;

    public object Clone()
    {
        return new Dude
        {
            Name = (string)this.Name.Clone(),
            LeftShoe = (Shoe)this.LeftShoe.Clone(),
            RightShoe = (Shoe)this.RightShoe.Clone()
        };
    }
}

最佳實踐

  1. 值類型首選 struct:小型、不可變、邏輯上為值(如 Point、DateTime、Money)。
  2. 引用類型需深拷貝:實現 ICloneable 或提供 Copy 方法,明確語義。
  3. 字符串特例:string 是引用類型但不可變,表現如值類型,無需手動 Clone。
  4. 避免可變結構體:會導致難以預期的拷貝行為(如 List.Enumerator)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型賦值/傳參行為內存分布
值類型 (struct)逐位拷貝數據內聯在包含者內部(棧或堆)
引用類型 (class)拷貝引用(指針)對象在堆,包含者存引用