到底是 const 还是 static readonly

时间:2023-03-08 17:15:50
到底是 const 还是 static readonly

真的一样?

const 和 static readonly 常在程序中用来声明常量,调用方法也没有什么不同,他们真的一样吗?我们可以做个试验。

程序集内的常量

现在我们建立一个程序,里面有一个MyClass的类,分别用const和static readonly定义常量

到底是 const 还是 static readonly

然后在程序运行时输出

到底是 const 还是 static readonly

运行程序,输出

到底是 const 还是 static readonly

把这两个值改一下,再运行

到底是 const 还是 static readonly

到底是 const 还是 static readonly

看来没什么问题

跨程序集的常量

现在我们建新建一个类库,创建一个类,同样的内容

到底是 const 还是 static readonly

在程序中加入对类库的引用,并把这两个常量输出

到底是 const 还是 static readonly

正常输出

到底是 const 还是 static readonly

改变这两个值

到底是 const 还是 static readonly

我们现在Rebuild那个类库(在类库上右键->Rebuild,不要Rebuild程序)

到底是 const 还是 static readonly

这样做是为了模拟在程序只对有更改的模块进行更新的情境,Rebuild好后,找到程序的生成目录,把新的DLL放进去,替换掉旧的,启动程序。

到底是 const 还是 static readonly

问题已经出来了,这样的结果不是我们想要的。

一切尽在IL

我们用ildasm打开exe看一下他的Main方法

到底是 const 还是 static readonly

我们可以看到,用const定义的常量在编译时是直接把值copy过来的,IL中就像对待字面量一样处理(是不是有点像C/C++的宏展开和内联?)而用static readonly定义的“常量”,在IL中就是一个加载成员变量的操作。

到底是 const 还是 static readonly

用const声明的常量,值在编译时计算,然后直接把常量的值嵌入到IL代码中,不会有栈操作,性能很高,也正因为这一点,const后面只能跟常量表达式,而且在跨程序集引用时,如果改变常量的值,则整个程序需要重新编译,看来const不是可以随便乱用的,如果某个值在以后的版本中可能会改变,那就不要用const,避免不必要的麻烦。

用static readonly 声明的并不能叫做常量,应该叫做只读变量,原因是它的值是在运行时进行计算的,因此具有很大的灵活性,它后面不仅仅可以跟常量表达式,还可以跟一个值只有在运行进才能确定的表达式,比如获取系统版本:

到底是 const 还是 static readonly

如果你追求性能,如果你足够谨慎,请用const,如果你想要灵活,想要安全,请用static readonly。