企业级开发中应按业务语义选择类型:独立不可变概念用基本类型或不可变引用类型,需身份与状态跟踪的实体用引用类型,性能敏感场景权衡结构体与引用类型,团队协作优先语义清晰、易于演进的封装类型。

在企业级开发中,选择基本类型(值类型)还是引用类型,核心取决于数据的语义、生命周期、性能要求和协作边界。不是“用哪个更高级”,而是“哪个更贴合业务事实”。
看数据是否代表独立、不可变的业务概念
如果一个字段天然具有明确业务含义、不依赖上下文、且不应被共享修改,优先用基本类型或不可变引用类型。
- 用基本类型:如订单金额(decimal)、用户年龄(int)、是否启用(bool)。它们轻量、线程安全、无空引用风险,语义干净。
- 用不可变引用类型:如自定义的 Money、PhoneNumber、OrderId。它们封装校验逻辑和行为(如 Money.Add()),避免原始类型被误用(比如把金额当整数做算术而不考虑货币精度)。
看对象是否需要身份识别与状态跟踪
当多个模块需协同操作同一业务实体,且它有唯一标识、可变状态、生命周期管理时,必须用引用类型(通常是领域模型类)。
- 例如:Customer 在订单服务、积分服务、风控服务中被反复引用——它不是“一份数据”,而是一个有身份的协作主体;它的地址、等级、信用分可能被不同服务更新,此时用 class Customer 是自然选择。
- 反例:若只是临时计算“客户近30天消费总额”,这个值本身无身份、不追踪变化,用 decimal 或只读结构体(readonly struct)更合适。
看性能与内存敏感度是否构成实际瓶颈
高频调用、大数据量、低延迟场景下,需主动评估类型开销,但不要过早优化。
- 大量小对象(如每秒百万级的传感器读数)→ 优先结构体(struct)减少 GC 压力,但需确保大小合理(一般 ≤16 字节为佳)且不可变。
- 跨进程/序列化场景(如微服务间 JSON 通信)→ 实际传输的都是数据快照,此时类型选择让位于契约(DTO),用简单引用类型(class)更清晰,无需纠结值/引用语义。
- 注意:.NET 中 string 是引用类型但表现得像值类型(不可变、重载 ==),这是语言层对业务直觉的妥协,可直接按“业务字符串”使用,不必强行替换成 ReadOnlySpan
除非真有性能证据。
看团队协作与演进成本
类型选择会影响 API 的理解成本和未来扩展空间。
- 用 int userId 看似简单,但一旦需要支持多租户 ID 格式(UUID / Snowflake / 复合键),所有用到 int 的地方都要改——换成 UserId 类型,约束和转换逻辑集中,演进平滑。
- 方法参数用基本类型(如 void Process(int id))虽快,但失去语义;改成 void Process(OrderId id),调用方一眼知其意,IDE 也能阻止传错类型(比如误传 CustomerId)。










