c# 深入理解static const readonly区别
Static 介绍
static 可以修饰class function field,标记字段是类型状态的一部分,而不是实例对象状态的一部分。
- 标记static的class 不能实例化,这些类只有静态成员(方法和属性),例如Math Console等类。
- CLR(common language runtime)调用class时,CLR利用程序集中该类的元数据,创建一个数据结构来表示类型本身,叫类型对象。
- 每一个类型对象都有一个方法表,在方法表中,类型定义的每个方法都有记录项,包括static的与非static的,只不过static的方法只可以直接通过类名调用,非静态方法只能通过对象的实例调用。
- 可以在类中定义的静态字段,静态字段在类型对象自身分配,而不是实例对象中,因此只有一份内存。
Const 介绍
const 常量是值不变化的符号,定义常量时,它的值必须能在编译时确定。确定后,编译器将常量值保存到程序集元数据中。这意味着编译器只能识别基本类型的常量。
- 常量总是被视为静态成员,而不是实例成员。
- 引用常量时,是将值直接嵌入IL代码中。由于直接嵌入代码,因此不需要运行时分配内存,也不能获取地址,引用。
- 常量只能在定义时赋值
ReadOnly 介绍
由于常量局限于基本数据类型,c# 增加readonly关键字,该关键字在编辑器和验证机制确保readonly标识的字段不会被构造器以外的任何方法写入。储存在每个实例对象中,每一个对象一份数据。
- 只能在定义时跟构造函数中赋值
- 可以通过反射修改 readonly 字段
- readonly 如果修饰的是引用类型,不可改变的是引用,引用对象的字段是可以修改的。
feild使用比较
关键字 | 内存占用 | 实例读取 | 类名读 取 | 写 | 说明 |
---|---|---|---|---|---|
static | 仅一份 | √ | √ | √ | 保存在类型对象中 |
const | 不占运行内存 | √ | √ | × | 元数据中保存了该值 |
readonly | 每个实例对象一份 | √ | × | × | 可以通过构造函数与反射修改 |
推荐使用方式
static:如果希望在所有实例对象共享一个数据,比方说程序需要静态配置的一些字段,多个实例对象计数器。但是static的字段一旦被加载就永久占用内存,特别如果static字段是一个引用类型,不使用了一定要记得置null,防止内存泄漏。
const:程序在计算过程中,存在一些不会变的值,比方说最大支持的人数100,最小等待时间5s,等等。如果单纯写一个值,会令他人感到疑惑,这个100代表什么,特别如果这样的值,被好几处代码使用,那么后期维护就需要每一处都去修改那个值,增加了维护难度。因此常量的使用主要是解决代码可读性与可维护性。
readonly : readonly 字段属于运行时常量,如果我们希望能定义一些字段,但是又担心别人会改变它,导致异常情况出现,可以使用readonly字段,在构造函数中给它赋初值。