required 修饰符(C# 参考)

required修饰符指示它应用于的字段属性必须由对象初始值设定项初始化。 初始化类型新实例的任何表达式都必须初始化所有 必需的成员。 修饰 required 符从 C# 11 开始可用。

C# 语言参考记录了 C# 语言的最新发布版本。 它还包含即将发布的语言版本公共预览版中功能的初始文档。

本文档标识了在语言的最后三个版本或当前公共预览版中首次引入的任何功能。

小窍门

若要查找 C# 中首次引入功能时,请参阅 有关 C# 语言版本历史记录的文章。

通过使用 required 修饰符,开发人员可以创建属性或字段必须正确初始化的类型,但仍允许通过对象初始值设定项进行初始化。 多个规则确保此行为:

  • required修饰符应用于在类型struct声明的字段和class属性,包括recordrecord struct类型。 不能将required修饰符应用于 .interface
  • 不能将显式接口实现 required标记为 . 不能在对象初始值设定项中设置它们。
  • 必须初始化所需的成员,但可以将其初始化为 null。 如果类型是不可为 null 的引用类型,编译器会在您将成员初始化为 null时发出警告。 如果未初始化成员,编译器将发出错误。
  • 必需的成员必须至少与其包含类型一样可见。 例如,public 类不能包含一个 required 字段,而该字段是 protected的。 此外,必需的属性必须具有设值器(setinit 访问器),这些访问器的可见性必须至少与其包含的类型一样高。 创建实例的代码无法设置无法访问的成员。
  • 派生类无法隐藏基类中声明的 required 成员。 隐藏必需的成员可防止调用方为其使用对象初始值设定项。 此外,重写必需属性的派生类型必须包含 required 修饰符。 派生类型无法删除 required 状态。 派生类型可以在重写属性时添加 required 修饰符。
  • 当类型参数包含new()约束时,不能将具有任何required成员的类型用作类型参数。 编译器无法强制在泛型代码中初始化所有必需的成员。
  • required不能将声明上的修饰符用于记录上的位置参数。 可以为包含 required 修饰符的位置属性添加显式声明。

某些类型(如 位置记录)使用主构造函数初始化位置属性。 如果其中任一属性包括 required 修饰符,则主构造函数将添加 SetsRequiredMembers 属性。 此属性指示主构造函数初始化所有必需的成员。 可以使用 System.Diagnostics.CodeAnalysis.SetsRequiredMembersAttribute 属性编写自己的构造函数。 但是,编译器不会验证这些构造函数是否确实初始化所有必需的成员。 相反,该特性向编译器断言构造函数会初始化所有必需的成员。 SetsRequiredMembers 属性将这些规则添加到构造函数:

  • 链接到使用 SetsRequiredMembers 属性注释的另一个构造函数的构造函数(this()base())还必须包含 SetsRequiredMembers 属性。 这可确保调用方能够正确使用所有适当的构造函数。
  • 对于 record 类型,如果其任何成员为 SetsRequiredMembers,生成的复制构造函数将应用 required 属性。

警告

SetsRequiredMembers 属性禁用编译器检查创建对象时是否初始化所有 required 成员。 请谨慎使用。

以下代码显示了一个类层次结构,该层次结构使用 requiredFirstName 属性的 LastName 修饰符:

public class Person
{
    public Person() { }

    [SetsRequiredMembers]
    public Person(string firstName, string lastName) =>
        (FirstName, LastName) = (firstName, lastName);

    public required string FirstName { get; init; }
    public required string LastName { get; init; }

    public int? Age { get; set; }
}

public class Student : Person
{
    public Student() : base()
    {
    }

    [SetsRequiredMembers]
    public Student(string firstName, string lastName) :
        base(firstName, lastName)
    {
    }

    public double GPA { get; set; }
}

有关所需成员的详细信息,请参阅 C#11 - 必需成员 功能规范。