将类作为方法参数时能否在编译期标记校验类的必填属性
编译期校验参数类必填属性的实现方案
你不需要完全依赖运行时检查,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,可以把所有必填参数放到类的构造函数中,可选属性保留为构造外可赋值的形式。编译器会在你创建类实例时强制要求传入构造函数定义的所有参数,漏传直接编译报错:
为了避免构造函数传参出现语义模糊的问题,调用时可以配合C#的命名参数语法,同样能保留清晰的可读性: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; } }var myClass = new MyClass( isDone: true, isNotDone: null, couldItBeDone: false, ifNotDone: true ); - 使用record类型(适配C# 9及以上版本)
这种方案本质和构造函数强制传参逻辑一致,只是语法更简洁,非常适合作为纯数据传递的参数载体:
record的属性默认是// 位置定义的属性默认都是必填项,初始化时必须传入 public record MyClass( bool IsDone, bool? IsNotDone, bool CouldItBeDone, bool IfNotDone ) { // 可选属性可单独在record体内定义,设置默认值 public string? Remark { get; init; } }init级别,初始化完成后不可修改,作为参数传递时安全性更高,调用时同样可以用命名参数保证可读性。
以上方案都可以覆盖你需要的编译期必填校验场景,只有涉及属性值的业务规则校验(比如数值范围限制、字符串格式要求等)时,才需要额外补充运行时检查。如果版本允许,优先选择
required修饰符的方案,改动最小也最贴合你现有的编码习惯。
内容的提问来源于stack exchange,提问作者ernest
相关产品推荐
相关产品推荐

