深入探讨C#中的const、readonly关键字
首先不可否认,这些在面试上会经常被面试官问起,但是你回答的让面试官满意吗?当然如果你知道了这些原理,或许你就不
怕了。既然说到了原理,我们还是从msdn说起。
一:值得推敲的几个地方
1.先来看看msdn上面对const是怎么说的,我们会看到。不能修改,编译时常量这些关键性信息。
q: const为什么不能被修改。
a:这个很简单,很多教科书上面都说,当编译器编译时,会将常量的值保存在该程序集的元数据中,下面我们做个实例
看一看。
①:新建一个projecta。
// projecta
public class testclass
{
public const int ctrip = int.maxvalue;
}
再建一个mainproject,引用下projecta。
using system;
class program
{
static void main(string[] args)
{
console.writeline(testclass.ctrip);
console.read();
}
}
然后我们把mainproject运行起来。
既然我把mainproject跑起来了,并且也引用了test.dll,刚才也说了,编译的时候会把常量值保存在程序集的元数据中,那我们
就找一找,打开ildasm.exe,并且ctrl+m。
很可惜,我并没有找到ctrip的符号,也没有找到int.maxvalue,也没有找到所谓的0x7fffffff,倒是找到了一个assembly的一些版本信息的元数据,那么这时候你可能会疑惑了,究竟const的值有没有保存到assembly里面去呢?很简单的一个验证方法就是,把mainproject下面bin中的test.dll删除掉,看看会有怎么样的奇迹发生。
②: 聪明的你应该想到了,既然运行demo.exe的时候不再加载test.dll,而是直接从demo的assembly里面获取const值,
那是不是会有断层的事情发生,也就是版本不一致的情况,比如我已经修改了const值,然后把编译好的dll拷贝到mainproject的bin目录下,直接运行demo.exe,会不会出现mainproject读不到修改后的const值呢?这里我将const改成 int.minvalue。
下面我们可以试试看。
// projecta
public class testclass
{
public const int ctrip = int.minvalue;
}
好了,看到上面的结果,就进一步佐证了刚才的说法,const确确实实是保存在assembly的元数据中,这里还要顺便提示一下,enum本质上是const,所以它也存在我刚才说的断层的问题,说到这里,我想你对const的原理应该比较熟悉了,现在我们来看看question的问题。既然是元数据,那什么是元数据?“描述数据的数据” 叫做元数据,既然它是基础的描述性数据,那么在定义好后是决对不能改变的,这个定义时也就是msdn说的编译时,是不是so easy呢?
q: const为什么要做成静态的,而不是做成实例的
a: 其实通过对第一个question的分析,很多东西我们应该都会豁然开朗,因为存在断层的问题,那么最好的方法就是const的值
永远也不要变,这样就可以避免问题的发生,既然是永远都不变的东西,当然是跟着“类型”走比跟着“实例”走要好的多,你说对不对,因为static是个小缓存,没必要new一下才产生。。。
q: readonly字段只能在ctor中初始化吗?
a:这个问题蛮有意思的,我们知道readonly的意思就是只读字段的意思,我们知道一般的字段具有可读写的功能,
先还是看看编译器怎么说。
从编译器上可以看到,确实readonly的初始化还可以在“变量初始化”的时候进行初始化,那么这样说question的答案应该就是否定的,但是真的是如此吗?我们都知道有一个东西叫做“语法糖”,而且经常是编译器提供给我们用的,所以真正的想看到发生了什么,只能用ildasm.exe 穿透编译器,看看到底发生了什么。
从il中可以看到,真的就是编译器的语法糖,本质上都是在ctor中初始化的,所以说,看问题千万不要看表面。
注:stsfld 用来自计算堆栈的值替换静态字段的值。
推荐阅读
-
深入探讨C#中的const、readonly关键字
-
C++中const的实现细节介绍(C,C#同理)
-
c#多线程中Lock()关键字的用法小结
-
C#中 const 和 readonly 的不同
-
php面向对象类中的$this,static,final,const,self及双冒号 : 这几个关键字使用方法
-
C#中实现线程同步lock关键字的用法详解
-
php面向对象类中的$this,static,final,const,self这几个关键字使用方法。
-
C#中的只读结构体(readonly struct)详解
-
php类中的$this,static,final,const,self这几个关键字使用方法_php实例
-
C#中dynamic关键字的正确用法(推荐)