C# 值类型和引用类型区别 C# struct和class在内存上有什么不同

来源:这里教程网 时间:2026-02-21 17:43:20 作者:

值类型直接存数据,引用类型只存地址——这是所有行为差异的起点。

struct 和 class 的内存分配位置不同

局部变量声明的

struct
实例(如
Point p = new Point(1, 2);
)通常整个结构体数据都落在栈上;而
class
实例(如
Person p = new Person();
)对象本体一定在堆上,栈上只存一个 4 或 8 字节的引用(指针)。

例外:当
struct
是某个
class
的字段时,它会随类一起被分配在堆上(不是栈)
栈内存自动释放,无 GC 开销;堆内存由垃圾回收器管理,有延迟和不确定性 频繁创建小
struct
(如
Vector2
)可显著降低 GC 压力;但大
struct
(比如超过 16 字节)栈拷贝开销反而升高

赋值时的行为差异:值拷贝 vs 引用拷贝

这是最常踩坑的地方——表面写法一样,底层语义完全不同。

struct
赋值是深拷贝:
s2 = s1
后修改
s2.X
不会影响
s1.X
class
赋值是浅拷贝:
c2 = c1
c2
c1
指向同一块堆内存,改一个就等于改了另一个
传参也一样:把
struct
传给方法,默认复制整块数据;
class
传参只复制引用,方法内修改对象状态会反映到调用方

默认值、null 和构造函数约束

这些限制都源于“值类型必须始终有确定值”这一设计前提。

struct
变量不能为
null
(除非显式声明为
Point?
),默认就是所有字段为零值(
X=0, Y=0
class
变量默认是
null
,不 new 就用会抛
NullReferenceException
struct
不允许定义无参构造函数(C# 10+ 允许
init
成员但仍有字段初始化强制要求),所有字段必须在构造中赋值
class
可自由定义任意构造函数,字段也能带默认值(
public int Count = 1;

真正难的不是记住区别,而是判断什么时候该用哪个——别光看“小数据用 struct”,还要看是否会被装箱、是否跨线程共享、是否要作为泛型约束(

where T : struct
)、甚至是否会被序列化成 JSON(某些库对 struct 的 null 处理更严格)。这些细节一漏,运行时表现就可能和预期南辕北辙。

相关推荐

热文推荐