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

C# 深拷貝與淺拷貝深度解析:值類型 vs 引用類型

     編輯:關於C

深拷貝與淺拷貝是理解 C# 內存模型的關鍵。本文通過值類型、引用類型、字符串、數組等實例,系統闡述拷貝行為差異與應對策略。

核心概念

類型拷貝行為典型例子
值類型深拷貝:逐位複製,互不影響int、double、struct、enum
引用類型淺拷貝:複製引用,共享堆上對象class、string、array、delegate

1. 值類型:天然深拷貝

int source = int.MaxValue;  // 2,147,483,647
int dest = source;          // 深拷貝,複製數值
dest = 1024;                // dest 變化
source = 2048;              // source 變化
// 兩者完全獨立,互不干擾

結構體示例

struct Point { public int X, Y; public Point(int x, int y) { X=x; Y=y; } }

Point s = new Point(10, 20);
Point d = s;      // 深拷貝,複製所有字段
d.X = 20;         // d.X=20, s.X=10 互不影響

2. 引用類型:預設淺拷貝


class Point { public int X, Y; public Point(int x, int y) { X=x; Y=y; } }

Point s = new Point(10, 20);
Point d = s;      // 淺拷貝,複製引用(地址)
d.X = 20;         // s.X 也變為 20!指向同一對象

內存圖解

棧                    堆
┌─────────┐         ┌──────────────┐
│ s  ─────┼────────►│ Point {10,20}│
└─────────┘         └──────────────┘
       ▲                   ▲
       │                   │
┌─────────┐         (同一對象)
│ d  ─────┘
└─────────┘

3. 引用類型如何深拷貝

手動新建 + 逐字段複製


Point d = new Point(s.X, s.Y);  // 或
Point d = new Point();
d.X = s.X; d.Y = s.Y;

ICloneable 接口


class Point : ICloneable {
    public int X, Y;
    public object Clone() => new Point(X, Y);  // 淺層字段深拷貝
}

序列化反序列化(深拷貝通用方案)


// BinaryFormatter (舊)、JSON.NET、MessagePack 等
string json = JsonConvert.SerializeObject(obj);
T copy = JsonConvert.DeserializeObject(json);

4. 特殊引用類型

類型行為原因
string表現為值類型不可變,任何修改都產生新對象
array淺拷貝複製引用,元素若為引用類型則共享
delegate淺拷貝複製委託引用,目標方法同一

字符串「深拷貝」假象


string s = "hello";
string d = s;        // 複製引用
d = "world";         // d 指向新字符串,s 不變
// 看似深拷貝,實則是不可變性導致

數組深拷貝


int[] src = {1, 2, 3};
int[] dst = new int[src.Length];
Array.Copy(src, dst, src.Length);  // 或 src.CopyTo(dst, 0)
// 值類型元素:深拷貝
// 引用類型元素:仍是淺拷貝(需逐元素 Clone)

5. 內部原理:引用類型雙重結構

  • 具名 Handle(變量):棧上,存儲地址
  • 內部對象:托管堆上,由 new 創建
  • 賦值 = 複製 Handle 的地址值
  • 可賦值為 null 是引用類型特徵

最佳實踐清單

  1. 值類型首選 struct:小數據、不可變、高頻分配
  2. 引用類型謹防共享副作用:傳參、返回、集合存儲時明確所有權
  3. 需要深拷貝時:實現 ICloneable、複製構造函數、或序列化
  4. 集合複製:list.ToArray()、new List(list) 均為淺拷貝
  5. 記錄類型:C# 9+ record 自帶值語義與 with 表達式

結語

深/淺拷貝本質是「數據所有權」與「共享可變狀態」的權衡。值類型通過複製消除共享,引用類型通過共享節省內存但引入耦合。理解這一點,配合 readonly、record、不可變模式等現代 C# 特性,能寫出更健壯、可維護的代碼。

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