带多构造函数的C# Record初始化遇CS9035错误,求解决方案
问题
我需要用record数组为数据库填充种子数据,对record类型的设计有以下要求:
- 所有必填属性通过构造函数传入,明确提示开发者哪些属性必填且不可为空;
- 提供无参构造函数,供Entity Framework Core实例化该
record; - 其中一个导航属性需声明为
virtual以实现懒加载,但主构造函数不支持virtual关键字,因此无法使用主构造函数。
最终定义的record代码如下:
[PrimaryKey(nameof(Id), nameof(Language))] public record DataText { [DatabaseGenerated(DatabaseGeneratedOption.None)] [Length(2, 200)] public required string Id { get; init; } public required virtual Language Language { get; init; } [Length(2, 3000)] public required string Text { get; init; } public DataText() { } public DataText(string id, Language language, string text) { Id = id; Language = language; Text = text; } }
但使用该record创建种子数据数组时:
DataText[] texts = [ new DataText($"{nameof(ProfileItem)}.{profileItems[0].Id}", de, "Titel") ];
出现编译错误CS9035:
CS9035: Required member 'DataText.Id' must be set in the object initializer or attribute constructor.
CS9035: Required member 'DataText.Language' must be set in the object initializer or attribute constructor.
CS9035: Required member 'DataText.Text' must be set in the object initializer or attribute constructor.
希望保留现有构造函数设计,且无法使用主构造函数,如何消除该错误?
解决方案
给初始化必填属性的普通构造函数添加[SetsRequiredMembers]特性即可解决问题。
修改后的代码
[PrimaryKey(nameof(Id), nameof(Language))] public record DataText { [DatabaseGenerated(DatabaseGeneratedOption.None)] [Length(2, 200)] public required string Id { get; init; } public required virtual Language Language { get; init; } [Length(2, 3000)] public required string Text { get; init; } public DataText() { } [SetsRequiredMembers] // 添加此特性 public DataText(string id, Language language, string text) { Id = id; Language = language; Text = text; } }
原理说明
[SetsRequiredMembers]是C# 10引入的特性,用于标记构造函数(或工厂方法)会初始化所有required修饰的成员。添加该特性后,编译器会认可此构造函数对必填属性的初始化操作,不再强制要求必须通过对象初始化器或主构造函数设置这些属性,从而消除CS9035错误。
此方案完全保留了你原有的设计:
- 无参构造函数依然存在,满足EF Core的实例化需求;
- 导航属性的
virtual修饰符保留,不影响懒加载; - 必填属性仍需通过指定构造函数传入,明确提示开发者必填项。
内容的提问来源于stack exchange,提问作者AxD
相关产品推荐
相关产品推荐

