目录
record class/readonly record struct/record struct
应用场景
- record可以用with关键字克隆出新的实体,而不是简单的引用传递。
- 如果两个实体是用record来声明的,那么可以比较两个实体的属性值是否都一致。
- 在进行实体输出时,如果该实体是用record声明的,那么输出的是该实体的内部数据结构,而不是一个类型的名称。
为什么要用record而不用结构体
- 为什么要用record而不用结构体,主要有三点原因。
- 第一个原因是因为结构体不支持继承。
- 第二个原因是因为结构体是值传递的过程,如果大量的结构体拥有着相同的数据,那么就会占用着不同的内存,导致内存浪费。
- 第三个原因是因为结构体的内部相等判断使用了ValueType.Equals方法,该方法是使用反射来实现的,因此性能不够快。
不适合的场景
record不适合在EFCore中使用,因为record重写了Equals方法和相等运算符(==和!=),这样可能会对EFCore的实体追踪机制造成影响。
不可变性
- record声明的实体具有不变性,因为该实体属性的setter是init,一旦初始化完成,它的属性值将不可修改。
- 虽然record声明的实体具有不可变性,但是可以通过自定义属性来覆盖原来的行为,让其属性变为可以修改。
自定义构造方法和属性
- record声明的实体在编译时会根据构造参数生成一个默认的构造函数,默认的构造函数不能被覆盖,如果有自定义的构造函数,那么需要使用this关键字来初始化这个默认的构造函数。
- record声明的实体中可以自定义属性,自定义属性名可以和构造参数名重名,也就是说自定义属性可以覆盖构造参数生成的属性,此时对应的构造参数将不起任何作用,但是可以通过属性指向这个构造参数来自定义这样一个属性。
解构
- record声明的实体在编译时会针对构造参数生成一个Deconstruct方法,用来支持解构。
- 解构只针对默认构造函数的构造参数。
继承
- record可以继承自record,但是record和类不能相互继承。
- 继承自record的子记录必须声明父记录中的各个参数。
值相等性
值相等性是值类型的一个概念,而record是引用类型,为了实现了值相等性,重写了Object的Equals和GetHashCode方法,重写了运算符==和!=,实现了IEquatable<T>接口。
非破坏性变化
- record声明的实体可以使用with关键字来实现非破坏性变化。
- 使用with关键字时会先调用<Clone>$()方法来创建一个对象,然后再对这个对象进行指定属性的初始 化。
record class/readonly record struct/record struct
- record class和readonly record struct生成的属性是get和init标识,也就是说它们的实体对象 是只读的。
- record struct生成的属性是get和set标识,也就是说它的对象是可读可写的。
- readonly record struct/record struct可以使用空构造函数初始化,可以不用with关键字进行克隆而直接 进行值复制。