You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用带init访问器的class与record有何差异?

带init访问器的class与record的核心区别

你写的这两段代码里,Student(class)和Student2(record)都用了init访问器,初始化后属性确实都没法修改,但两者的核心差异体现在设计语义和自动生成的功能上:

先贴出你的代码:

class Student
{
    public int Id { get; init; }
    public string? Name { get; init; }
}

record Student2
{
    public int Id { get; init; }
    public string? Name { get; init; }
}

具体区别如下:

  • 语义本质不同:record是值语义类型,默认比较的是实例的属性值;class是引用语义类型,默认比较的是内存地址。比如两个Student实例的Id和Name完全一样,student1 == student2会返回false,因为它们是不同的对象;但两个Student2实例做同样的比较会返回true,因为record默认按属性值判断相等。
  • 自动生成的实用成员差异:record会自动帮你生成一堆常用方法,不用自己写:
    • 重写的Equals方法和IEquatable<T>实现,专门处理值相等判断
    • 重写的GetHashCode,保证属性相同的实例哈希码一致
    • 格式化的ToString,输出类似Student2 { Id = 1, Name = "张三" }的字符串,方便调试
    • 解构方法,支持var (id, name) = student2直接提取属性值
    • With表达式,比如var updatedStudent = student2 with { Name = "李四" },快速创建仅修改部分属性的新不可变实例
      而class不会自动生成任何这些成员,所有相等判断、哈希码、ToString都得自己手动实现。
  • 继承特性不同:record支持继承,子类record会自动继承父类的相等逻辑、ToString等行为;class的继承就是普通的引用类型继承,没有这些语义层面的自动继承特性。
  • 不可变场景适配性:虽然两者都通过init实现了属性不可变,但record的设计初衷就是作为不可变数据载体,配合With表达式能更便捷地处理不可变数据的更新;class的init只是限制了属性的修改时机,本质还是引用类型,更多用于面向对象的行为封装,而非纯数据承载。

内容的提问来源于stack exchange,提问作者Steve

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 22:39:25