Skip to content

C# record

专门用于简化不可变数据对象的定义。它的主要作用是处理那些数据导向(data-centric)对象,尤其是当你想要一个简洁的、不可变的类,并希望能够方便地比较对象的值,而非它们的引用。

简洁了一些

用来做dto的定义蛮好的

csharp
public record Person(string FirstName, string LastName);

自动生成一些对我们有用的成员函数.

构造函数:根据定义的属性自动生成构造函数。 属性:自动生成只读属性。 Deconstruct 方法:用于解构记录对象,对于习惯写TS的小伙伴相当友好。 Equals 和 GetHashCode 方法:基于属性值的相等性比较。 ToString 方法:提供友好的字符串表示,对于调试输出特别友好。 基于值的相等性语法. 我们很多时候有这种需求就是比较一个类的所有属性来判断逻辑.如果使用 record 的话 我们只需要==或者Equals就能判断,

这样如果要把一个类当成 Dictionary的Key是很方便的,不需要自己去重写GetHashCode

非破坏性复制值

对于一个 class 的浅表复制,我们可能需要实现ICloneable,亦或者 new 一个对象逐个属性赋值,当然还有其他的方法,但是呢肯定是没有 record 来的这么简单直接.我们仅需要一个with关键字就干完了 比如我们从一个static cache里面拿出一个对象,在某些情况下想要改变它的值使用With就特别的方便。

csharp
public record Person(string FirstName, string LastName, int Age);
var person1 = new Person("vip", "wan", 18);
var person2 = person1 with { Age = 30 };
Console.WriteLine(person1); // 输出: Person { FirstName = vip, LastName = wan, Age = 18 }
Console.WriteLine(person2); // 输出: Person { FirstName = vip, LastName = wan, Age = 30 }

解构的支持

record 类型自动生成 Deconstruct 方法,允许你轻松地解构 record 对象,对于全栈的同学书写就是手到擒来!

csharp
var person = new Person("vip", "wan", 18);
var (firstName, lastName, age) = person;
Console.WriteLine(firstName); // 输出: vip
Console.WriteLine(lastName);  // 输出: wan
Console.WriteLine(age);       // 输出: 18

结合模式匹配 record 类型与模式匹配功能很好地集成在一起,使得在模式匹配中使用 record 对象更加方便。

csharp
public record Person(string UserName, int Age);
public string GetPersonInfo(Person person) => person switch
{
    { Age: < 18 } => "Minor",
    { Age: >= 18 } => "Adult",
    _ => "Unknown"
};

微软的Orleans shopping cart例子里面用到了它。

简单就是美