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

C#9 如何无需显式构造函数强制构造时初始化必填属性

C# 强制必填属性初始化(无构造函数冗余)实现方案

你遇到的是C#版本迭代中专门被解决的典型痛点,不需要手写重复的构造函数样板代码,根据你使用的C#版本可以选择以下原生方案:


首选方案:C# 11+ 原生required修饰符

C# 11正式引入的required关键字就是专门为了解决这个场景设计的:只需要在属性定义前加上required修饰符,编译器就会强制要求所有创建该类型实例的代码,必须通过对象初始化器给该属性赋值,缺省直接报编译错误(不是可空引用类型那种可配置的警告),完全不需要手写任何显式构造函数。

修改后的代码示例:

public record Person
{
    // 仅需加required关键字
    public required string Name { get; init; }

    public static void Make()
    {
        // 👇 这行直接触发编译错误:未初始化必填成员"Name"
        new Person { };

        // ✅ 正确写法
        new Person { Name = "Li Ming" };
    }
}

这个方案的特点完全匹配需求:

  • 零冗余代码:不需要重复写构造函数参数、构造函数赋值逻辑,只需要在属性定义处加一个关键字
  • 编译期校验:没有运行时反射/校验开销,校验逻辑完全在编译阶段完成
  • 适配所有类型:class、record、struct都支持,不管属性是init还是普通set访问器都可以标记为required
  • 支持例外场景:如果是序列化、工厂方法等场景确实需要跳过校验,只需要给对应方法加[SetsRequiredMembers]特性,告诉编译器该方法已经保证初始化了所有必填成员即可。

版本说明:只要使用Visual Studio 2022及以上版本自带的Roslyn编译器,即使项目目标框架是.NET 6甚至更旧的版本,也可以通过修改csproj文件中的<LangVersion>latest</LangVersion>配置启用C# 11语法,不需要升级目标框架。


record专属极简方案:主构造函数

如果你不需要坚持用对象初始化器的赋值风格,record类型本身的主构造函数语法从C# 9发布开始就支持零冗余的必填参数定义:

// 👇 一整行就完成了定义,编译器自动生成init-only的Name属性,且强制构造时必须传参
public record Person(string Name);

public static void Make()
{
    // 👇 编译错误:构造Person缺少必填参数Name
    new Person();

    // ✅ 正确写法
    var p = new Person("Li Ming");
}

这个写法比required更简洁,但缺点是必须按构造函数参数顺序传值,不支持纯对象初始化器的赋值方式,适合参数少、参数顺序固定的场景。


旧版本兼容说明

如果你还在使用C# 11以下的版本,没有原生语法可以直接实现你要的效果:

  • 内置方案只能手写显式构造函数,把所有必填属性作为构造函数参数,确实会产生你说的三遍重复代码
  • 如果不想手写重复代码,可以借助第三方源生成器,在编译期自动生成包含所有必填属性的构造函数,避免手动维护冗余逻辑。

内容的提问来源于stack exchange,提问作者DivergentSpaceTimeWanderer

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.27 01:45:41