c# class 和 struct 的区别

11次阅读

Struct 还是 class 取决于三点:是否需共享状态、是否频繁复制、是否需要继承或虚方法;struct 赋值为值拷贝(含引用字段浅拷贝),class 为引用拷贝;struct 必须显式初始化所有字段,无参构造受限;仅当满足纯数据载体、≤16 字节、极少修改时才优先选 struct。

c# class 和 struct 的区别

选 class 还是 struct?核心就看三点:要不要共享状态、会不会频繁复制、需不需要继承或虚方法。其他都是衍生影响。

赋值和传参时行为完全不同

这是最常踩坑的地方——你以为改的是副本,结果改了别人的数据,或者反过来。

  • class 赋值或传参时只拷贝引用地址,c2 = c1c1c2 指向同一块内存
  • struct 赋值或传参时默认拷贝整个值(浅拷贝),s2 = s1 后修改 s2.X 不会影响 s1.X
  • ⚠️ 注意:如果 struct 里包含 Stringclass 字段,拷贝的只是那个引用,不是深层对象——这叫“值语义 + 引用字段”,容易误判为深拷贝
struct Point { public int X; public int Y; public string Tag; } class Entity { public int Id; public string Name; } 

var p1 = new Point { X = 1, Y = 2, Tag = "A" }; var p2 = p1; p2.X = 99; p2.Tag = "B"; // ✅ p1.Tag 仍是 "A" —— string 是不可变引用,赋新值不改变原引用

var e1 = new Entity { Id = 1, Name = "Alice" }; var e2 = e1; e2.Name = "Bob"; // ✅ e1.Name 也变成 "Bob"

构造函数和初始化规则差异很大

struct 的构造函数不是“可选功能”,而是强制约束:你写的每个构造函数都必须显式初始化所有字段。

  • class 可以只写带参构造,也能用无参 new MyClass()(编译器自动补默认构造)
  • struct 不能定义无参构造函数(C# 10+ 允许但仅限于 init 成员场景,日常仍应避免)
  • struct 总有隐式无参构造:直接声明 Point p; 就能用,p.X 自动是 0
  • ❌ 下面代码会编译失败:
    struct BadPoint { public int X; public BadPoint(int y) { /* 忘了赋 X */ } }

什么时候该用 struct?别凭感觉,看这 3 个硬指标

不是“小就用 struct”,而是满足全部三条才考虑:

  • 逻辑上是“纯数据载体”,比如 Vector3ColorDateOnly,不封装行为或状态机
  • 大小稳定且 ≤ 16 字节.net 推荐阈值),避免溢出或复制开销过大
  • 设计为不可变(readonly struct)或极少修改——因为每次赋值都在复制,改得勤反而更慢
  • ✅ 推荐场景:Span 内部字段、DTO 中的坐标/金额/时间戳结构体、数学库中的向量/矩阵
  • ❌ 禁止场景:含 Eventvirtual 方法、大数组字段、需要 IDisposable 的类型

最容易被忽略的一点:struct 在 class 字段里、数组里、async 状态机里,其实都分配在堆上——“struct 在上”只是局部变量的常见情况,不是铁律。性能优化前,先用 dotnet-countersPerfView 看真实分配行为,别靠直觉猜。

text=ZqhQzanResources