C# 内存机制详解:值类型、引用类型与 String 的不可变性


C# 内存机制详解:值类型、引用类型与 String 的不可变性

1. 值类型 (Value Type)

代表类型: int, bool, struct, double, char 等。

特点

  • 存储位置: 变量名和实际数据都保存在 栈 (Stack) 中。
  • 赋值行为: 直接拷贝一份完整的数据。修改其中一个,另一个不受影响。

代码示例

csharp 复制代码
int a = 10;
int b = a; // 拷贝具体的值
b = 20;    // 修改 b,a 依然是 10

内存图解

text 复制代码
栈 (Stack)                 堆 (Heap)
+----------+----------+   +-------------------+
| 变量名    |   数据   |   |                   |
+----------+----------+   |                   |
|    a     |    10    |   |  (值类型不占用堆)   |
+----------+----------+   |                   |
|    b     |    20    |   |                   |
+----------+----------+   +-------------------+

2. 引用类型 (Reference Type)

代表类型: class, interface, array, delegate 等。

特点

  • 存储位置: 栈中存的是 内存地址 (指针) ,实际的对象内容存在 堆 (Heap) 中。
  • 赋值行为: 拷贝的是地址。两个变量指向同一个堆对象。

代码示例

csharp 复制代码
Person p1 = new Person { Name = "Alice" };
Person p2 = p1;  // 拷贝地址,两人指向同一个对象
p2.Name = "Bob"; // 通过 p2 修改堆内容,p1.Name 也会变成 "Bob"

内存图解

text 复制代码
栈 (Stack)                          堆 (Heap)
+----------+-----------+           +--------------------------+
| 变量名    |  内存地址  |           |        对象实际数据        |
+----------+-----------+           +--------------------------+
|   p1     |  [0x001]  | --------> | 地址[0x001]: {Name:"Bob"} |
+----------+-----------+      /    +--------------------------+
|   p2     |  [0x001]  | ----/     (p1和p2共享同一块堆空间)
+----------+-----------+

3. String 的特殊性:不可变的引用类型

string 是引用类型,但在行为上表现得像值类型,这就是因为它的 不可变性 (Immutability)

核心规则

一旦在堆上创建了字符串对象,它的内容就永远不能被修改。 所有的"修改"操作实际上都是在堆中创建了一个全新的字符串对象,并让变量指向新地址。

代码演示与内存步解

csharp 复制代码
string s1 = "Hi";
string s2 = s1; // s2 指向与 s1 相同的地址
s2 = "Yo";      // 并不是修改 "Hi",而是新开辟空间存 "Yo"
第一步:执行 s1 = "Hi"; s2 = s1;
text 复制代码
栈 (Stack)                          堆 (Heap)
+----------+-----------+           +---------------------+
| 变量名    |  内存地址  |           |      字符串对象      |
+----------+-----------+           +---------------------+
|   s1     |  [0xAAA]  | --------> | [0xAAA]: "Hi"       |
+----------+-----------+      /    +---------------------+
|   s2     |  [0xAAA]  | ----/
+----------+-----------+
第二步:执行 s2 = "Yo";
text 复制代码
栈 (Stack)                          堆 (Heap)
+----------+-----------+           +---------------------+
| 变量名    |  内存地址  |           |      字符串对象      |
+----------+-----------+           +---------------------+
|   s1     |  [0xAAA]  | --------> | [0xAAA]: "Hi"       |
+----------+-----------+           +---------------------+
|   s2     |  [0xBBB]  | --------> | [0xBBB]: "Yo"       |
+----------+-----------+           +---------------------+

4. 总结对比表

特性 值类型 (Value Type) 引用类型 (Reference Type) String (特殊引用类型)
存储位置 栈 (Stack) 栈(地址) + 堆(对象) 栈(地址) + 堆(对象)
赋值行为 拷贝具体数值 拷贝内存地址 拷贝内存地址
修改行为 原地修改变量值 原地修改堆中的对象内容 禁止原地修改,创建新对象并更向新地址
典型代表 int, struct class, array string

为什么 String 要这样设计?

  1. 性能与内存: 支持"字符串驻留",相同内容的字符串在内存中只存一份。
  2. 安全: 字符串作为参数传递(如文件路径)时,不会在途中被意外修改。
  3. 线程安全: 多个线程同时读一个不可变对象,不需要加锁。

提示:在进行大量字符串拼接操作时,请务必使用 StringBuilder 以避免在堆中产生大量无用的中间字符串碎片。

相关推荐
torpidcat4 小时前
ruoyi-vue-pro 若依芋道 java springboot +mybatis 生日查询相关
java·vue.js·spring boot
AC赳赳老秦4 小时前
文旅市场公开数据分析:基于 OpenClaw 采集景区客流与门票公示数据,生成区域文旅热度监测报告
java·c语言·python·php·symfony·deepseek·openclaw
我命由我123455 小时前
Windows 操作系统 - 启用 D 盘虚拟内存
java·运维·服务器·windows·学习·java-ee·运维开发
xcl09255 小时前
智慧场馆解决方案系统源码:从架构设计到部署实战
java·spring boot
liangbo75 小时前
06-JVM垃圾回收器之CMS
java·jvm
黑马程序员毕设5 小时前
基于Java的仪器管理系统设计与实现
java·开发语言·spring boot·后端·微信小程序
骇客野人6 小时前
SpringBoot电商购物车、结算、下单、库存方案设计与落地实施步骤
java·spring boot·后端
哪 吒6 小时前
华为OD机试 - 云服务安全策略最优选择 - 深度优先搜索DFS(Java 新系统 200分)
java·华为od·深度优先
拒绝内耗。6 小时前
程序员学架构(一):一张图看懂 Java 后端架构:一个请求怎样从手机到数据库?
java·智能手机·架构
棣廷6 小时前
初识Python面向对象
java·开发语言