C#中如何创建继承其他记录属性的记录?能否提取参数简化维护?
在C#中实现记录继承与参数复用方案
问题1:继承基类记录属性且无需显式重写的实现方式
在C# 9及以上版本中,原生支持记录的继承特性,要让派生记录自动复用基类的属性,无需显式重写,核心是通过构造函数传递基类所需参数,结合记录的位置语法特性来实现,具体有两种常用方式:
方式1:位置记录的标准继承写法
如果基类是用位置参数声明的记录,派生记录只需在继承时通过: Base(参数)的形式,将基类所需的参数传递过去,同时声明自身独有的属性即可:
public record Base(int Param1, int Param2, int Param3); // 派生记录A,传递基类参数并声明自有属性Something public record A(int Param1, int Param2, int Param3, int Something) : Base(Param1, Param2, Param3); // 派生记录B同理 public record B(int Param1, int Param2, int Param3, string OtherThing) : Base(Param1, Param2, Param3); // 派生记录C直接复用基类所有参数 public record C(int Param1, int Param2, int Param3) : Base(Param1, Param2, Param3);
这种方式下,派生记录会自动继承基类的所有属性,无需手动重写,同时保留自身的独有属性。
方式2:无参构造函数+对象初始化器
如果希望派生记录的声明更简洁,可以给基类添加无参构造函数并设置属性为init模式,之后在创建实例时通过对象初始化器赋值:
public record Base { public int Param1 { get; init; } public int Param2 { get; init; } public int Param3 { get; init; } } public record A(int Something) : Base; public record B(string OtherThing) : Base; public record C() : Base; // 实例化时赋值基类属性 var a = new A(10) { Param1 = 1, Param2 = 2, Param3 = 3 };
这种方式牺牲了位置记录的简洁性,但提升了实例创建的灵活性,适合对初始化逻辑有特殊要求的场景。
问题2:提取共享参数到基类实现可维护性优化
完全可以将重复的参数提取到基类记录中,实现代码的统一维护,你提出的核心思路是正确的,但需要调整语法以符合C#的编译规则(原期望代码会因未传递基类位置参数报错),以下是正确的实现方案:
优化后的可维护代码
public record Base(int Param1, int Param2, int Param3); // 派生记录接收基类参数并传递,同时声明自有属性 public record A(int Param1, int Param2, int Param3, int Something) : Base(Param1, Param2, Param3); public record B(int Param1, int Param2, int Param3, string OtherThing) : Base(Param1, Param2, Param3); // C记录无自有属性,直接复用基类参数 public record C(int Param1, int Param2, int Param3) : Base(Param1, Param2, Param3);
这样当需要修改Param1的类型、名称或添加新的共享参数时,只需修改基类Base的定义,所有派生记录会自动同步,无需逐个修改,大幅提升代码可维护性。
C# 10+的简化写法
在C# 10及以上版本,若派生记录无需添加新属性,可以直接继承基类,省略重复的参数声明:
public record Base(int Param1, int Param2, int Param3); // C记录无自有属性,直接继承基类 public record C : Base; // 实例化时直接使用基类的位置参数 var c = new C(1, 2, 3);
额外注意点
- 位置记录的继承必须保证派生记录的主构造函数能正确传递基类所需的位置参数,否则会触发编译错误。
- 若基类使用
sealed修饰符,则无法被其他记录继承。 - 记录的
with表达式会自动包含基类属性,派生记录使用with时可直接修改基类属性:var a = new A(1,2,3,10); var newA = a with { Param1 = 100 }; // 直接修改基类的Param1属性
内容的提问来源于stack exchange,提问作者AoooR
相关产品推荐
相关产品推荐

