关键字 init (C# 参考)

init 关键字在属性或索引器中定义访问器方法。 init-only 资源库仅在对象构造期间为属性或索引器元素赋值。 init 强制实施不可变性,因此,一旦初始化对象,将无法更改。 init 访问器使调用代码能够使用对象初始值设定项来设置初始值。 相比之下,只有 get setter 的自动实现属性必须通过调用构造函数来初始化。 具有 private set 访问器的属性可在构造后修改,但只能在类中修改。

以下代码演示 init 自动实现的属性中的访问器:

class Person_InitExampleAutoProperty
{
    public int YearOfBirth { get; init; }
}

可能需要实现其中一个访问器来提供参数验证。 可以使用 C# 13 中作为预览功能引入的 field 关键字执行此操作。 关键字 field 访问该属性的编译器合成后盾字段。 以下示例显示了一个属性, init 其中访问器验证参数的范围 value

class Person_InitExampleFieldProperty
{
    public int YearOfBirth
    {
        get;
        init
        {
            field = (value <= DateTime.Now.Year)
                ? value
                : throw new ArgumentOutOfRangeException(nameof(value), "Year of birth can't be in the future");
        }
    }
}

重要

关键字 field 是 C# 13 中的预览功能。 必须使用 .NET 9 并将元素preview设置为<LangVersion>项目文件中,才能使用field上下文关键字。

应注意在 field 具有名为 field字段的类中使用关键字功能。 新 field 关键字将隐藏属性访问器范围中命名 field 的字段。 可以更改变量的名称 field ,或使用 @ 令牌将标识符引用 field@field。 可以通过阅读关键字的功能规范field来了解详细信息。

init 访问器可用作表达式主体成员。 示例:

class Person_InitExampleExpressionBodied
{
    private int _yearOfBirth;

    public int YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}

以下示例为名为 YearOfBirth 的属性同时定义 getinit 访问器。 它使用名为 _yearOfBirth 的私有字段备份属性值。

class Person_InitExample
{
     private int _yearOfBirth;

     public int YearOfBirth
     {
         get { return _yearOfBirth; }
         init { _yearOfBirth = value; }
     }
}

init 访问器不强制调用方设置属性。 而它允许调用方使用对象初始值设定项,同时禁止以后的修改。 可以添加 required 修饰符以强制调用方设置属性。 以下示例显示了一个以可为空的值类型作为支持字段的仅 init 属性。 如果调用方未初始化 YearOfBirth 属性,该属性的默认值 null 为:

class Person_InitExampleNullability
{
    private int? _yearOfBirth;

    public int? YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}

若要强制调用方设置初始非 null 值,可添加 required 修饰符,如以下示例所示:

class Person_InitExampleNonNull
{
    private int _yearOfBirth;

    public required int YearOfBirth
    {
        get => _yearOfBirth;
        init => _yearOfBirth = value;
    }
}

以下示例显示了 private set、read only 和 init 属性之间的区别。 private set 版本和 read only 版本都需要调用方使用添加的构造函数来设置 name 属性。 通过 private set 版本,人员可在构造实例后更改其名称。 init 版本不需要构造函数。 调用方可使用对象初始值设定项初始化属性:

class PersonPrivateSet
{
    public string FirstName { get; private set; }
    public string LastName { get; private set; }
    public PersonPrivateSet(string first, string last) => (FirstName, LastName) = (first, last);

    public void ChangeName(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonReadOnly
{
    public string FirstName { get; }
    public string LastName { get; }
    public PersonReadOnly(string first, string last) => (FirstName, LastName) = (first, last);
}

class PersonInit
{
    public string FirstName { get; init; }
    public string LastName { get; init; }
}
PersonPrivateSet personPrivateSet = new("Bill", "Gates");
PersonReadOnly personReadOnly = new("Bill", "Gates");
PersonInit personInit = new() { FirstName = "Bill", LastName = "Gates" };

C# 语言规范

有关详细信息,请参阅 C# 语言规范。 该语言规范是 C# 语法和用法的权威资料。

另请参阅