请阐述 C# 中 const 和 readonly 的关键差异,并说明它们在编译期和运行期的行为有何不同?
考察说明
考查对 C# 中常量(const)和只读字段(readonly)的区分理解,重点在于编译期与运行期行为、赋值时机以及适用场景。
回答思路
- 【回答框架 1】const 是编译期常量,值在编译时确定并直接嵌入到使用处(如 IL 代码中),因此必须用字面量或常量表达式初始化,且在声明时就必须赋值,之后无法更改。readonly 是运行期常量,本质是只读字段,值在对象实例化时(构造函数中)或声明时赋值,之后不能再修改,但每次创建实例时都可以有不同的值。
- 【回答框架 2】const 默认是静态成员,属于类型本身,不能与 static 关键字同时使用,且只能用于基本类型(如 int、string、bool 等),不能用于自定义类或结构体的实例字段。readonly 可以是实例字段(在构造函数中赋值)或静态字段(在静态构造函数中赋值),不限于基本类型,可以是任何类型的引用,但引用本身不可变,引用对象内部状态仍可变。
- 【回答框架 3】编译期的差异:const 的值在编译时已确定,使用时直接替换为值,不产生字段访问,因此无需实例即可访问(通过类型名),但修改 const 值需要重新编译所有引用它的代码。readonly 的值在运行时才确定,通过字段访问,修改后只需重新编译定义它的程序集,引用它的程序集无需重新编译即可看到新值(除非被链接为内联)。
- 【回答框架 4】适用场景:const 适用于永不变化的值,如数学常数、固定字符串等,性能较好。readonly 适用于需要根据外部条件或实例状态决定的值,如从配置文件读取的初始化值、依赖构造函数参数的字段等,灵活性更高。
- 【回答框架 5】补充:const 不能使用 new 关键字,而 readonly 可以。若需定义一个可作为 const 使用的自定义类型常量,只能使用 static readonly 配合静态构造函数模拟,但不能获得 const 的编译期嵌入行为。
- 【关键点 1】const 是编译期常量,readonly 是运行期只读字段。
- 【关键点 2】const 必须在声明时初始化,readonly 可在构造函数或声明时初始化。
- 【关键点 3】const 默认静态,readonly 可以是实例或静态字段。
- 【关键点 4】修改 const 值需重编译引用方,修改 readonly 值只需重编译定义方。
- 【关键点 5】readonly 仅保证引用不可变,不保证引用对象内部状态不可变。
- 【易错点 1】容易误认为 readonly 是运行期常量,可随意在运行时修改,实际上除构造函数外不能赋值。
- 【易错点 2】将 const 用于可变需求场景,导致改值后依赖程序集未更新而出现旧值。
- 【易错点 3】以为 readonly 字段可以用于常量表达式,实际上 readonly 不能用于 const 的初始值,因为 const 需要编译期确定值。