三亩地 三亩地SAN MU DI · CODE DIARY
ARTICLE DETAIL

日记详情

真实记录编程学习的某一天,欢迎挑你感兴趣的翻一翻。

C#新手向:搞懂“值类型”与“引用类型”及其对程序性能的影响

C#新手向:搞懂“值类型”与“引用类型”及其对程序性能的影响
int a = 10; int b = a; b = 20; // 此时 a 还是 10,没问题。 List<int> list1 = new List<int> { 1, 2, 3 }; List<int> list2 = list1; list2.Add(4); // 此时 list1 里竟然也变成了 {1, 2, 3, 4}?!

这背后的“罪魁祸首”就是我们要聊的值类型(Value Type)​ 和引用类型(Reference Type)

1. 核心概念:快递柜 vs 仓库门牌号

在C#中,所有类型都派生自System.Object,但内存分配方式截然不同。

📦 值类型:自带储物柜(Stack)

代表成员struct(结构体)、enum(枚举)、intfloatdoublebool

想象一下你去超市存包,使用的是自带锁的储物柜

  • 你(a变量)手里拿着钥匙,柜子里直接放着你的物品(数值10)。

  • 当你复制给b时,系统直接拷贝了一份物品放到另一个空柜子里。

  • 结果:两个柜子互不干扰,你把b柜子里的东西换成20a柜子里的10毫发无伤。

🏠 引用类型:租了一个大仓库(Heap)

代表成员class(类)、interface(接口)、stringarray(数组)、delegate

想象一下你租了一个巨大的物流仓库。

  • 你(list1变量)手里拿的不是货物,而是一张仓库的门牌号(地址/指针)

  • 当你把门牌号给了list2时,你们俩手里拿的是同一张门牌号

  • 结果:你们指向的是同一个仓库。无论谁往里面搬货(Add(4)),对方去看的时候,仓库里的东西肯定变多了。

2. 了解内存:Stack(栈)与 Heap(堆)

光靠比喻还不够,我们要稍微深入一点点底层(放心,不难)。

特性值类型(Value Type)引用类型 (Reference Type)
存储位置通常存储在栈 (Stack)​ 上数据存储在堆 (Heap)​ 上,引用地址存储在栈上
赋值行为复制数据本身​ (拷贝)复制引用地址​ (浅拷贝)
内存释放离开作用域立即释放GC (垃圾回收器)​ 定期清理
访问速度快 (CPU缓存命中率高)相对慢 (需要寻址)
// 值类型示例 int num1 = 100; int num2 = num1; // 复制了 100 这个数字 // 引用类型示例 Person p1 = new Person() { Age = 18 }; Person p2 = p1; // 复制了 "new Person()" 这个对象的内存地址 p2.Age = 20; Console.WriteLine(p1.Age); // 输出 20 (因为 p1 和 p2 指向同一个人)

3. 总结与最佳实践

为了写出高性能的C#代码,请记住这几点:

  1. 简单数据用struct(值类型):当你只需要封装少量数据(如坐标 Point、颜色 Color、复数 Complex),且没有继承需求时,用structclass更快,因为不需要GC介入。

  2. 大对象用class:如果对象很大,或者需要被多处共享(如配置对象、服务实例),用class

  3. 不要过度优化:过早优化是万恶之源。99%的情况下,代码可读性和业务逻辑正确更重要。只有在性能瓶颈分析(Profiling)后,再去抠这些细节。

← 返回列表