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

将类作为方法参数时能否在编译期标记校验类的必填属性

编译期校验参数类必填属性的实现方案

你不需要完全依赖运行时检查,C#本身提供了原生能力可以实现编译阶段的必填项校验,同时保留参数类封装带来的可读性,常用方案如下:

  • 使用C# 11及以上版本内置的required修饰符
    这是最贴合你现有编码习惯的方案。首先在项目配置中开启可空引用类型检查(将Nullable节点设为enable),之后只需要在参数类的必填属性前加上required关键字即可:
    public class MyClass
    {
        public required bool IsDone { get; set; }
        // 不允许为null的属性不要加?可空标记,同时标注required
        public required bool? IsNotDone { get; set; }
        public required bool CouldItBeDone { get; set; }
        public required bool IfNotDone { get; set; }
        // 可选属性不需要加required,可设置默认值
        public string? Remark { get; set; }
    }
    
    标注完成后,如果你在使用对象初始化器创建实例时漏写了任意一个required属性,编译器会直接抛出错误,阻断编译流程,完全实现编译期校验。你之前用属性名明确参数含义的写法不需要做任何改动,可读性不受影响。
    注意:required修饰符的校验仅针对对象初始化器场景,如果你先创建空实例再逐行给属性赋值,编译器无法识别漏赋值的问题,这类场景需要额外注意。
  • 构造函数强制传参(适配C# 11以下版本)
    如果你的项目使用的C#版本低于11,可以把所有必填参数放到类的构造函数中,可选属性保留为构造外可赋值的形式。编译器会在你创建类实例时强制要求传入构造函数定义的所有参数,漏传直接编译报错:
    public class MyClass
    {
        // 所有必填参数放入构造函数
        public MyClass(bool isDone, bool? isNotDone, bool couldItBeDone, bool ifNotDone)
        {
            IsDone = isDone;
            IsNotDone = isNotDone;
            CouldItBeDone = couldItBeDone;
            IfNotDone = ifNotDone;
        }
    
        public bool IsDone { get; set; }
        public bool? IsNotDone { get; set; }
        public bool CouldItBeDone { get; set; }
        public bool IfNotDone { get; set; }
        // 可选属性不放入构造函数,设置默认值
        public string? Remark { get; set; }
    }
    
    为了避免构造函数传参出现语义模糊的问题,调用时可以配合C#的命名参数语法,同样能保留清晰的可读性:
    var myClass = new MyClass(
        isDone: true,
        isNotDone: null,
        couldItBeDone: false,
        ifNotDone: true
    );
    
  • 使用record类型(适配C# 9及以上版本)
    这种方案本质和构造函数强制传参逻辑一致,只是语法更简洁,非常适合作为纯数据传递的参数载体:
    // 位置定义的属性默认都是必填项,初始化时必须传入
    public record MyClass(
        bool IsDone,
        bool? IsNotDone,
        bool CouldItBeDone,
        bool IfNotDone
    )
    {
        // 可选属性可单独在record体内定义,设置默认值
        public string? Remark { get; init; }
    }
    
    record的属性默认是init级别,初始化完成后不可修改,作为参数传递时安全性更高,调用时同样可以用命名参数保证可读性。

以上方案都可以覆盖你需要的编译期必填校验场景,只有涉及属性值的业务规则校验(比如数值范围限制、字符串格式要求等)时,才需要额外补充运行时检查。如果版本允许,优先选择required修饰符的方案,改动最小也最贴合你现有的编码习惯。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.17 16:16:01