C#中readonly,const限制变量修改的关键字
·
在 C# 中,readonly 和 const 都是用于限制变量修改的关键字,但它们的作用时机、适用场景和特性有显著区别。结合你的代码示例,具体解释如下:
1. const(常量)—— 编译时确定的不可变值
代码示例:
private const int GripSize = 8;//控制点的矩形长宽
核心特性:
- 编译时常量:
const修饰的变量值在编译阶段就已确定,并被嵌入到编译后的代码中(类似 “硬编码”)。运行时无法修改,也不会分配独立的内存空间。 - 必须在声明时初始化:声明时必须赋值,且值必须是 “编译时可计算的常量”(如数值、字符串、枚举值等),不能依赖运行时才能确定的值(如变量、方法返回值)。
- 适用类型有限:只能修饰值类型(如
int、float、bool)或字符串(string),不能修饰引用类型(如List<Shape>、object等)。 - 作用域内共享:
const是 “类型级别的常量”,所有实例共享同一个值,不存在 “每个实例一个常量” 的情况。
在代码中的意义:
GripSize 表示 “控制点的矩形长宽”(如选中 ROI 时边缘显示的小方块大小),这个值是固定不变的(业务上不需要动态调整)。用 const 修饰的原因:
- 编译时确定值,访问效率极高(直接读取硬编码的值);
- 明确告知编译器和开发者:这个值永远不会变,避免意外修改。
2. readonly(只读字段)—— 运行时确定的不可变引用
代码示例:
private readonly List<Shape> shapes = new List<Shape>();//ROI集合
核心特性:
- 运行时常量:
readonly修饰的字段值在运行时确定,可以在声明时初始化,也可以在构造函数中初始化(但只能初始化一次)。 - 不可二次赋值:对象创建后(构造函数执行完毕),
readonly字段的引用(或值)不能被修改。但如果是引用类型(如集合、类实例),其内部内容可以修改(仅限制 “引用本身不可变”)。 - 适用类型广泛:可以修饰任何类型(值类型、引用类型均可)。
- 实例级别的只读:每个类实例可以有自己的
readonly字段值(如果在构造函数中根据参数初始化)。
在代码中的意义:
shapes 是存储 ROI 的集合(List<Shape>),用 readonly 修饰的原因:
- 确保
shapes这个字段不能被重新赋值为另一个List<Shape>实例(避免意外替换整个集合); - 但允许修改集合的内部内容(如通过
shapes.Add()添加 ROI、shapes.Remove()删除 ROI),这符合业务需求(ROI 集合需要动态增删,但集合本身不能被替换); - 可以在构造函数中根据需要初始化(例如从外部加载已有 ROI 到集合中),灵活性高于
const。
const vs readonly 关键区别总结
| 特性 | const |
readonly |
|---|---|---|
| 确定时机 | 编译时 | 运行时(构造函数执行时) |
| 初始化位置 | 必须在声明时 | 声明时或构造函数中 |
| 可修饰类型 | 仅值类型、字符串、枚举 | 任何类型(值类型、引用类型) |
| 能否修改 | 永远不能修改 | 构造函数执行后不能修改(引用不变) |
| 引用类型处理 | 不支持(无法修饰引用类型) | 允许修改内部内容(仅限制引用本身) |
总结
const用于编译时就确定且永不改变的简单值(如固定尺寸、常量参数),例如代码中的GripSize(控制点大小固定)。readonly用于运行时初始化且引用(或值)不可二次修改的字段,尤其适合引用类型(如集合、对象),例如代码中的shapes(集合本身不能被替换,但内容可动态修改)。
两者的核心目的都是 “限制修改”,但根据值的确定时机和类型选择使用,以保证代码的安全性和合理性。
更多推荐
所有评论(0)