C#中的init關鍵字

從C# 9開始,引入了init關鍵字,其目的是確保類中的屬性(property)僅在對象被構造的時候才允許被賦值,聽起來好像與C# 6中的自動屬性構造函數初始化(auto-property constructor initialization)的方式有些類似,但由init定義的類屬性,允許在調用方初始化對象時,對這樣的屬性初始化一次,而不僅僅是侷限於構造函數中。 比如下面的代碼,在C# 6中可以直接在構造函數中初始化Value屬性的值:

class MyClass
{
    public MyClass()
    {
        Value = "A";
    }

    public string Value { get; }
}
或者可以寫成下面的樣子:
class MyClass
{
    public MyClass() { }

    public string Value { get; } = "A";
}
但是,如果在調用方需要初始化Value的值,則上面的寫法是沒辦法做到這一點的:
// Error CS0200 Property or indexer 'MyClass.Value' cannot be assigned to -- it is read only
MyClass a = new MyClass { Value = "B" };
從語言特性上說,如果把Value屬性改爲可讀寫的屬性,也就是:
public string Value { get; set; } = "A";
那麼上面報錯的代碼編譯當然可以通過,不過這又使得Value屬性在所有能夠被訪問到的地方,都能夠改變它的值。爲了解決這種更細粒度的訪問控制,C# 9引入init關鍵字,對於使用了init關鍵字的屬性,允許調用方在初始化的時候對其賦值一次,之後如果再次賦值,就會出現編譯錯誤:
MyClass a = new MyClass { Value = "B" }; // OK

// error CS8852: Init - only property or indexer 'MyClass.Value'
// can only be assigned in an object initializer, or on 'this' or 'base'
// in an instance constructor or an 'init' accessor.
a.Value = "C";  

class MyClass
{
    public MyClass() { }

    public string Value { get; init; } = "A";
}
和property setter一樣,init也可以通過類裏的字段(field)來保存屬性值:
class MyClass
{
    private string _value;
    public MyClass() { }

    public string Value
    {
        get { return _value; }
        init { _value = value; }
    }
}
或者直接使用表達式:
class MyClass
{
    private string _value;
    public MyClass() { }

    public string Value
    {
        get => _value;
        init => _value = value;
    }
}
 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章