readonly 只读字段的初始化值确定|static 字段的初始值确定
readonly
关键字是一个可在四个上下文中使用的修饰符:
-
在字段声明中,
readonly
指示只能在声明期间或在同一个类的构造函数中向字段赋值。 可以在字段声明和构造函数中多次分配和重新分配只读字段。构造函数退出后,不能分配
readonly
字段。 此规则对于值类型和引用类型具有不同的含义:- 由于值类型直接包含数据,因此属于
readonly
值类型的字段不可变。 - 由于引用类型包含对其数据的引用,因此属于
readonly
引用类型的字段必须始终引用同一对象。 该对象是可变的。readonly
修饰符可防止字段替换为引用类型的其他实例。 但是,修饰符不会阻止通过只读字段修改字段的实例数据。
警告
包含属于可变引用类型的外部可见只读字段的外部可见类型可能存在安全漏洞,可能会触发警告 CA2104:“不要声明只读可变引用类型。”
- 由于值类型直接包含数据,因此属于
-
在
readonly struct
类型定义中,readonly
指示结构类型是不可变的。 有关详细信息,请参阅结构类型一文中的readonly
结构一节。 -
在结构类型内的实例成员声明中,
readonly
指示实例成员不修改结构的状态。 有关详细信息,请参阅结构类型一文中的readonly
实例成员部分。 -
在
ref readonly
方法返回中,readonly
修饰符指示该方法返回一个引用,且不允许向该引用写入内容。
类的初始化顺序 如下:
第一次实例化Son============================
C#编译器缺省将每一个成员变量初始化为他的默认值
Son静态字段
Son静态构造函数
Son字段
Father静态字段
Father静态构造函数
Father字段
Father 构造函数
Son构造函数
Son对象初始值设定项
第N次(N>1)的实例化Son============================
Son字段
Father字段
Father 构造函数
Son构造函数
Son对象初始值设定项
readonly字段是 运行时常量,它的值取决初始化方式,只有在对象实例化完成后 readonly 字段的值才最终确定下来。
静态readonly字段 的初始值是在 静态构造函数执行完成后就确定值了。
实例readonly字段 在实例化过程中可以通过init 属性和索引器赋值,也就是说 对象初始值设定项完成后才确定的,
readonly 运行时常量 在类初始化的过程中可以被多次赋值,可以在字段声明处 赋值 ,也可以在类的构造函数中赋值,也可以在init 访问器中赋值。
以下就是两种方式方式初始化 readonly字段,导致两个不同的值:
public readonly string A1 = "10"; public A(string a) => A1 = a; public string B { get => A1; init => A1 = value; } static void Main(string[] args) { A a = new A("a") { B = "A" }; A b = new A("a"); Console.WriteLine($"a={a.A1} b={b.A1}"); Console.ReadKey(); }
static 字段的初始化
静态字段可以在声明处 初始化,也可以 在静态构造函数中初始化 。