C#中的init关键字

By | 2023年1月2日

从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;
    }
}

 

(总访问量:567;当日访问量:1)
Category: C# 标签:

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据