编译时常量和运行时常量
定义
1 | //编译时常量 |
编译时常量可以在方法体中声明,运行时常量不能在方法体中重声明
不同
1、编译时常量和运行时常量访问方式不同导致不同的行为。在目标代码中编译时常量会被替换成常量值。
比如下面代码:
1 | // Compile time constant: |
会和下面写法的编译的 IL 代码是一样的:
1 | if (myDateTime.Year == 2000) |
运行时常量的值是在运行时得到的。当你引用一个只读(read-only)常量, IL 会引用一个 readonly 变量而不是直接使用值。
2、修饰的类型不同
使用编译时常量和运行时常量还有不同的限制。编译时常量只能在基本类型(内建整数和浮点数类型),枚举类型,或字符串。编译时常量要求类能用有意义的常量赋值初始化。而只有基本类型才能在 IL 代码中使用常量(literal values)来替换。不能使用使用 new 操作法初始化编译时常量,即使它是一个值类型:
1 | // Does not compile, use readonly instead: |
编译时常量只能使用与数字和字符串。只读(Read-only)变量也是常量,即不能在构造函数完成之后再修改。但只读变量是在运行时赋值。这会比编译时常量更灵活。首先,运行时常量可以是任何类型。你必须在构造函数或者直接初始化。你可以让 DateTime 结构体变为 readonly 值;但不能使用 const 创建 DateTime 值。
3、确定值的时机不一样
只读变量最重要的不同在于运行时才确定值。当你引用一个只读变量, IL 会为你产生一个指向只读变量的引用,而不是值。这种差异将对维护上产生深远的影响。编译时常量产生的 IL 代码就跟直接使用数值变量时一样的,即使是跨程序集:一个程序集的常量在另一个程序集还是被替换为数值。
换句话说,更改const定义的常量值,程序都需要重新编译
4、性能
已知的常量值会比使用变量访问的 readonly 变量产生稍微高效的代码。然而,性能上甚微的收效和灵活性的减小应该做一个很好的权衡。放弃灵活性之前一定要剖析性能差异。
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.