record 是 C# 9.0 引入的轻量级引用类型,专为不可变数据建模设计,自动提供值语义、ToString()、位置解构和 with 表达式;支持位置声明与类体形式,with 实现浅拷贝式副本修改,但需注意其引用本质与浅拷贝限制。

record 是 C# 9.0 引入的轻量级引用类型,专为不可变数据建模设计,自动提供值语义(如 Equals、GetHashCode)、ToString()、位置解构和 with 表达式等能力,省去大量样板代码。
声明 record 的基本语法
最简形式用 record 关键字加类名和括号内属性列表(位置 record):
public record Person(string Name, int Age);
编译器自动生成:私有只读字段、公有 init-only 属性、构造函数、相等比较逻辑、格式化字符串输出等。
你也可以写成类体形式(非位置 record),手动定义属性,但需显式标记 init 以保持不可变性:
public record Student
{
public string Id { get; init; }
public string Name { get; init; }
public int Grade { get; init; }
}使用 with 表达式创建副本并修改部分字段
with 是 record 的核心特性之一,用于基于现有实例生成新实例(浅拷贝),只改指定字段,其余保持不变:
-
✅ 正确用法:
var adult = person with { Age = 18 }; -
✅ 支持嵌套修改:
var updated = student with { Name = "Alice", Grade = 95 }; -
❌ 不能用于普通 class:只有 record 或继承自 record 的类型支持
with。
自定义 record 行为(可选)
record 默认是不可变且按值比较的,但你可以按需扩展:
- 重写
ToString():public override string ToString() => $"[{Name}, {Age}]"; - 添加方法或只读属性:
public bool IsAdult => Age >= 18; - 支持解构:
public void Deconstruct(out string name, out int age) => (name, age) = (Name, Age);,之后可用var (n, a) = person; - 继承 record:
public record Employee(string Name, int Age, string Department) : Person(Name, Age);
注意事项和常见误区
record 不是万能替代 class 的方案:
- 它默认是引用类型,不是值类型(别和
struct混淆); - 字段仍是引用,
with只做浅拷贝——若含可变引用对象(如List),内部内容仍共享; - 不支持无参构造函数(位置 record 必须传参),如需默认实例可加静态只读字段:
public static readonly Person Empty = new("", 0);; - 在需要频繁修改状态的场景(如 UI ViewModel、DTO 绑定),传统 class + 属性通知可能更合适。
基本上就这些。record 适合表达“数据是什么”,而不是“数据能做什么”。用对了,代码更简洁、语义更清晰。










