record struct 是 c# 10 引入的只读值类型记录,专为小数据、高性能、不可变场景设计;它必须显式或隐式声明为 readonly,不支持 with 表达式、继承和堆分配,属于 struct 类型,可被 where t : struct 约束匹配。

record struct 是 C# 10 引入的值类型记录,不是 class 的轻量替代,而是为小数据、高性能、不可变场景专门设计的结构体 —— 它不支持 with,不能继承,也不分配在堆上。
record struct 必须显式或隐式 readonly
编译器强制要求 record struct 是只读的。省略 readonly 关键字会直接报错:CS8861: 'record struct' must be declared 'readonly'。
常见写法有三种:
-
public readonly record struct Person(string Name, int Age);(隐式 readonly,推荐) -
public record struct Person(string Name, int Age);(C# 10+ 不合法,编译失败) -
public readonly record struct Point { public double X { get; init; } public double Y { get; init; } }(显式字段/属性,但所有成员必须是init或get-only)
一旦出现 set、field initializer(如 int Count = 0;)或可变字段,编译器立刻拒绝。
record struct 不支持 with 表达式
with 是 record class 的核心特性,依赖引用语义和“复制后修改”逻辑;而 record struct 是值类型,天然按值传递,没有“原地复制再改”的语义基础。
以下代码会编译失败:
var p1 = new Point(1.0, 2.0);
var p2 = p1 with { X = 3.0 }; // CS0571: 'Point.with' is not accessible
如果你需要类似行为,得手动构造新实例:var p2 = new Point(3.0, p1.Y);,或者封装成方法:public Point WithX(double x) => new(x, Y);。
record struct 在泛型约束中属于 struct 类型
它能被 where T : struct 正确匹配,但不能用于 where T : class。
这意味着你可以安全地把它用在高性能泛型容器里,比如:
public static T Identity<t>(T value) where T : struct => value; var p = new Point(1.0, 2.0); var same = Identity(p); // ✅ 编译通过 </t>
注意:如果泛型方法内部做了装箱(例如传给 object 参数),会触发隐式堆分配,抵消 record struct 的性能优势 —— 这类路径要格外留意。
解构和 ToString 等行为需留意初始化方式
主构造参数(如 Person(string Name, int Age))自动支持解构和默认 ToString();但若改用显式属性写法,Deconstruct 方法不会自动生成,必须手动实现才能用 var (name, age) = person;。
同样,ToString() 默认输出类似 Person { Name = "Alice", Age = 30 },但若你重写了它(如返回 "({X:F2}, {Y:F2})"),要注意格式字符串里的精度控制会影响调试体验和日志可读性。
最容易被忽略的一点:虽然它是值类型,但作为方法参数时仍是按值传递 —— 修改形参不会影响实参,这点和普通 struct 一致,和 record class 完全不同。











