required修饰符仅适用于类或结构体的实例属性/字段,必须配合init或set使用,用于编译期强制初始化,不适用于方法、参数或static成员。

required修饰符只能用于属性和字段,不能用于方法
很多人搜“required修饰符方法”,其实是误解了语法作用域。required是C# 11引入的修饰符,只允许加在类/结构体的实例属性或字段上(且必须是可空引用类型或值类型),目的是让对象初始化时**必须显式赋值**,否则编译报错。它和方法定义、调用、参数修饰完全无关——你没法给void DoSomething()加required,也不支持required string name作为方法参数。
如何正确使用 required 强制初始化属性
核心是配合record或普通类 + init访问器,确保构造后不可变且初始化不被跳过:
-
required必须和init或set搭配,不能单独用于get;只读属性 - 仅对实例成员有效,
static required string Name会编译失败 - 使用对象初始化器时,未提供
required成员会触发CS8852错误:“无法为必需的成员‘X’赋值” - 若用构造函数初始化,
required成员仍需在构造函数体内显式赋值(或通过this()链式调用传递)
示例:
public class Person
{
public required string Name { get; init; }
public required int Age { get; init; }
}
<p>// ✅ 正确:对象初始化器中全部提供
var p = new Person { Name = "Alice", Age = 30 };</p><p>// ❌ 编译错误:缺少 required 成员 Age
// var p2 = new Person { Name = "Bob" };required 不等于构造函数参数强制,要注意初始化路径
即使加了required,如果类有无参构造函数且没封禁,依然可能绕过初始化(比如反序列化、反射创建):
-
JsonSerializer.Deserialize<person>(json)</person>默认不会校验required,除非启用JsonSerializerOptions.RequireExplicitNullValueHandling = true(.NET 8+) - 用
Activator.CreateInstance<person>()</person>能绕过,此时required字段为null或default,但运行时不报错——这是设计使然,required是编译期契约,非运行时防护 - 若想彻底杜绝未初始化实例,建议结合私有构造函数 + 工厂方法,或用
record(自动禁用无参构造)
替代方案:何时该用 init-only + 构造函数,而非 required
当需要更细粒度控制(比如部分字段必须传参、部分可选、部分依赖计算)时,required反而不够灵活:
-
required所有标记成员必须“同进同出”,无法表达“Name必填,Email可选但格式要校验”这类逻辑 - 构造函数内可做参数验证(
if (string.IsNullOrWhiteSpace(name)) throw ...),而required只管是否赋值,不管值是否合法 - 若属性需延迟初始化(如依赖注入服务),
required会直接卡住,此时更适合用??=或Lazy<t></t>
简单说:required解决的是“漏填”问题,不是“填错”或“填得不及时”问题。










