You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

带多构造函数的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:22:22