共用方式為


關鍵字 init (C# 參考)

init 關鍵字會在屬性或索引子中定義存取子方法。 僅限 init 的 setter 只會在物件建構期間將值指派給屬性或索引子元素。 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 = (YearOfBirth <= DateTime.Now.Year)
                ? value
                : throw new ArgumentOutOfRangeException(nameof(value), "Year of birth can't be in the future");
        }
    }
}

重要

關鍵詞 field 是 C# 13 中的預覽功能。 您必須使用 .NET 9,並將項目 <LangVersion> 檔中的 元素設定為 preview ,才能使用 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 唯一具有可為 Null 實值型別作為其支援欄位的屬性。 如果呼叫端未初始化 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、唯讀和 init 屬性之間的差異。 私人集版本和唯讀版本都需要呼叫端使用新增的建構函式來設定 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# 語法及用法的限定來源。

另請參閱