导读:本期聚焦于小伙伴创作的《.NET中的Record类型是什么?编写不可变数据模型的简洁之道》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《.NET中的Record类型是什么?编写不可变数据模型的简洁之道》有用,将其分享出去将是对创作者最好的鼓励。

在C#9.0及更高版本的.NET生态中,Record类型是一种专门面向不可变数据场景设计的引用类型,它从语法层面简化了不可变数据模型的构建过程,避免了传统类实现不可变属性时需要编写的大量重复代码。Record类型默认将属性设置为不可变,同时内置了值相等性判断、解构、友好的字符串输出等常用功能,让开发者可以用极简的语法完成不可变数据类型的开发。

.NET中的Record类型是什么?编写不可变数据模型的简洁之道

Record类型的基础定义

Record类型的定义语法非常简洁,最常见的形式是使用位置参数定义,编译器会自动生成对应的不可变属性和构造函数。示例如下:

// 定义包含姓名和年龄的Person Record
public record Person(string Name, int Age);

// 使用位置参数创建实例
Person person1 = new Person("张三", 25);
// 也可以显式指定属性名创建
Person person2 = new Person(Name: "李四", Age: 30);

上述代码定义了一个Person Record,包含两个不可变属性Name和Age。编译器会自动生成以下内容:

  • 两个只读的init-only属性Name和Age
  • 包含对应参数的构造函数
  • 基于所有属性的Equals和GetHashCode方法
  • 重写的ToString方法,输出格式化的属性信息
  • 解构方法,支持将实例的属性拆分到变量中

Record类型的核心特性

不可变性

Record类型的属性默认是init访问器,只能在对象初始化时赋值,后续无法修改。如果尝试修改属性值,编译器会直接报错:

Person person = new Person("张三", 25);
// 以下代码会编译报错,因为Age是init-only属性
// person.Age = 26;

值相等性

普通类的相等性判断默认是引用相等,即两个对象指向同一个内存地址才判定为相等。而Record类型默认实现值相等性,只要两个实例的所有属性值都相同,就判定为相等:

Person p1 = new Person("张三", 25);
Person p2 = new Person("张三", 25);
// 输出True,因为值相等
Console.WriteLine(p1 == p2);
// 普通类的话这里会输出False

with表达式

Record类型支持with表达式,可以基于现有实例创建一个新实例,仅修改指定属性的值,其他属性保持原值,非常适合不可变数据的浅拷贝场景:

Person person = new Person("张三", 25);
// 创建新实例,年龄改为26,姓名保持不变
Person newPerson = person with { Age = 26 };
Console.WriteLine(newPerson);
// 输出 Person { Name = 张三, Age = 26 }

解构支持

Record类型自动生成解构方法,可以直接将实例的属性拆分到对应变量中:

Person person = new Person("张三", 25);
// 解构实例,获取Name和Age
(string name, int age) = person;
Console.WriteLine($"姓名:{name},年龄:{age}");
// 输出 姓名:张三,年龄:25

Record类型与普通类的区别

虽然Record本质是引用类型,但和普通类有诸多不同,我们可以通过下表清晰对比两者的差异:

对比维度普通类Record类型
属性默认可变性默认可读可写默认init-only,不可变
相等性判断引用相等值相等
ToString方法输出类型全名输出格式化的属性键值对
样板代码量实现不可变需要手动写大量代码语法简洁,自动生成常用方法
with表达式支持不支持原生支持

Record类型的适用场景

Record类型非常适合以下场景:

  • DTO(数据传输对象),尤其是API接口的请求和响应模型
  • 领域模型中的值对象,比如订单号、金额、地址等不可变概念
  • 临时数据容器,需要频繁创建、比较、传递的场景
  • 需要值相等性判断的引用类型场景

进阶用法:自定义Record

如果需要添加自定义方法或者修改默认行为,也可以像普通类一样扩展Record类型:

public record Person(string Name, int Age)
{
    // 添加自定义方法
    public string GetDescription()
    {
        return $"{Name}今年{Age}岁";
    }
    
    // 重写默认的ToString方法
    public sealed override string ToString()
    {
        return $"人员信息:姓名{Name},年龄{Age}";
    }
}

// 使用自定义Record
Person person = new Person("张三", 25);
Console.WriteLine(person.GetDescription());
// 输出 张三今年25岁
Console.WriteLine(person);
// 输出 人员信息:姓名张三,年龄25

需要注意的是,Record类型支持继承,但是只能继承自其他Record类型,不能继承自普通类,普通类也不能继承自Record类型。例如可以定义Student Record继承自Person Record:

public record Student(string Name, int Age, string School) : Person(Name, Age);

Student student = new Student("张三", 25, "XX大学");
Console.WriteLine(student);
// 输出 Student { Name = 张三, Age = 25, School = XX大学 }

总的来说,Record类型是.NET中编写不可变数据模型的高效工具,它平衡了代码的简洁性和功能的完备性,在合适的场景下使用可以大幅减少重复代码,提升开发效率。

Record类型不可变数据模型C#9.0值相等性修改时间:2026-06-11 10:21:42

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。