C# init用法
init是什么意思?
init就 modreq([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) 类型的缩写
modreq= Modified Request:修改请求
IsExternalInit=is Externa Init(initialize):是外部初始化 。
所以init 完整的意思就是 修改请求(在外部初始化的时候)
总的功能就是扩大readonly实例字段的赋值方式,C#9之前readonly实例字段只能在字段初始值设定项和实例构造函数中赋值(静态只读字段还是只有两种赋值方式)。C#9 推出init 以后,readonly实例字段可以多一种赋值方式,可以在对象初始值设定项中赋值。
动机
自1.0 以来,用 c # 生成不可变数据的基础机制并未更改。 它们仍保留:
1.将字段声明为 readonly 。
2. 声明仅包含 get 访问器的属性。
这些机制在允许构造不可变的数据时有效,但它们通过向类型的样板代码添加成本并从对象和集合初始值设定
项的功能中选择此类类型来实现此目的。 这意味着开发人员必须在易用性和不可变性之间进行选择。
像声明类型一样,简单的不可变对象(例如 Point )需要两个样板板代码,以支持构造。 类型越大,此样板板式的
成本就越大:
struct Point { public int X { get; } public int Y { get; } } public Point(int x, int y) { this.X = x; this.Y = y; }
init 的作用
总的功能就是扩大readonly实例字段的赋值方式,C#9之前readonly字段只能在字段初始值设定项和实例构造函数中赋值。C#9 推出init 以后,readonly实例字段可以多一种赋值方式,可以在对象初始过程中通过属性和索引器赋值,也就是说可以通过对象的初始值设定项 赋值。
1、 init访问器(只替代set访问器),用在属性和索引器中。 对象的构造阶段 init访问器可以使用,对象实例完成后init访问器不可使用。对象初始化完成后init对应的属性就是readonly字段。
类的初始化顺序:https://www.cnblogs.com/cdaniu/p/15308485.html
2、允许 init 作为字段修饰符
3、init
修饰符可以扩展以应用于所有实例成员
4、允许 init 作为类型修饰符
init 访问器
init访问器(只替代set访问器),用在属性和索引器中。 对象的构造阶段 init访问器可以使用,对象实例完成后init访问器不可使用。对象初始化完成后init对应的属性就是readonly字段。
public class Test { static void Main(string[] args) { var d = new Derived(); } } class Base { public bool Value { get; init; } } class Derived : Base { public Derived() { // Not allowed with get only properties but allowed with init Value = true; } }
modreq= Modified Request:修改请求
IsExternalInit=is Externa Init(initialize):是外部初始化,init其实就是 IsExternalInit的简写。init是个修饰符。
所以init 完整的意思就是 修改请求(在外部初始化的时候)
上面这张图就已经很清晰的解释了,init就 modreq([System.Runtime]System.Runtime.CompilerServices.IsExternalInit) 。init的功能就是这个修饰符的功能。
当init在做属性访问器器时,它是带了修饰符的set访问器。完成对 私有只读字段 的封装。换句话说我们可以把readonly实例字段放在 init访问器中初始化。
init只能用于实例化属性(索引)中
readonly字段初始化只有两种方式:声明时和构造函数中,但从 C# 9开始 readonly 实例字段 多了一个属性赋值方式,也就是对象初始值设定项中赋值。实例化完成后就不能使用属性化赋值
使用了init修饰的属性,则不需要定义构造函数,直接在对象初始化器中赋值即可。
这样就可以再对象和集合初始值设定项中初始化属性。拓展初始值设定像功能,。
init
访问器可设置的规则围绕类型层次结构扩展。 如果该成员是可访问的,并且已知该对象处于构造阶段,则该成员是可设置的。 这就是:
对象最初进行实例化的时期。这个初始化过程称为构造阶段
class Base { public bool Value { get; init; } } class Derived : Base { Derived() { // Not allowed with get only properties but allowed with init Value = true; } } class Consumption { void Example() { var d = new Derived() { Value = true; }; } }
2、允许 init 作为字段修饰符
同样, init
也可以作为属性访问器,它也可以作为字段的指定,将其作为 init
属性提供。 这将允许在类型、派生类型或对象初始值设定项完成构造之前,对字段进行赋值。
class Student { public init string FirstName; public init string LastName; } var s = new Student() { FirstName = "Jarde", LastName = "Parsons", }
在元数据中,这些字段将以与readonly
字段相同的方式进行标记, 但使用附加的属性 modreq 指示它们是 init
样式字段。
4、允许 init 作为类型修饰符
将init用修饰类型时,类型中所有实列字段成员都可以被修饰撑init,这一点不同于readonly,readonly修饰的所有实例成员都是readonly。
再结构类型中使用init
struct Point { public init int X; public init int Y; } // vs. init struct Point { public int X; public int Y; }