在C#中定义常量的方式有两种,

一种叫做静态常量(Compile-time constant),另一种叫做动态常量(Runtime constant)。

前者用“const”来定义,后者用“readonly”来定义。

对于静态常量(Compile-time constant),它的书写方式如下:     public const int MAX_VALUE = 10;

为什么称它为静态常量呢,因为如上声明可以按照如下理解(注意:如下书写是错误的,会出编译错误,这里只是为了方便说明)。

public static const int MAX_VALUE = 10;

用const定义的常量,对于所有类对象而言都是一样的,因此需要像访问静态成员那样去访问const定义的常量,而用对象的成员方式去访问会出变异错误。

此外,对于静态常量的访问在编译的时候,是用常量的值去替换常量,

例如:       int nValue = MAX_VALUE;

这句在编译之后,和如下这句所产生的中间语言代码是一样的。

int nValue = 10;

不过,在用const来定义常量的时候,在类型上有很多限制。首先,此类型必须属于值类型,同时此类型的初始化不能通过new来完成,因此一些用struct定义的值类型常量也不能用const来定义。

相对于const而言,用readonly来定义常量要灵活的多,它的书写方式如下:

public readonly int MAX_VALUE = 10;

为什么称为动态变量,因为系统要为readonly所定义的常量分配空间,即和类的其他成员一样拥有独立的空间。此外,readonly所定义的常量除了在定义的时候可以设定常量值外,还可以在类的构造函数中进行设定。由于readonly所定义的常量相当于类的成员,因此使用const来定义常量所受到的类型限制,在使用readonly去定义的时候全部消失,即可以用readonly去定义任何类型的常量。  综合上面所述,至于对比两者之间的区别具体如下。

静态常量(Compile-time constant)   动态常量(Runtime constant)

定义   声明的同时要设置常量值。声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置。

类型限制   首先类型必须属于值类型范围,且其值不能通过new来进行设置。 没有限制,可以用它定义任何类型的常量。

对于类对象而言    对于所有类的对象而言,常量的值是一样的。 对于类的不同对象而言,常量的值可以是不一样的。

内存消耗    无。 要分配内存,保存常量实体。

综述    性能要略高,无内存开销,但是限制颇多,不灵活。 灵活,方便,但是性能略低,且有内存开销。

对于在定义常量的时候,到底是用const来定义还是readonly来定义,我以前为了追求性能,因此尽量用const来定义。但是在此书中,提到了一个关于使用const会产生潜在的bug。就是在程序中使用DLL类库某个类的静态常量时,如果在类库中修改静态常量的值,其它接口没有发生变化,一般来说,程序调用端是不需要重新编译,直接执行就可以调用新的类库。不过就是在此情况下,会产生潜在的bug。这是由于静态常量在编译的时候,是用它的值去替换常量,因此在调用端的程序也是这样进行替换的。例如:在类库中定义了一个静态常量,如下:
   public const int MAX_VALUE = 10;       那么对于程序中调用此静态常量这段代码,在编译后产生的中间语言代码中,是用10来进行替换,

即使用静态常量的地方,改为10了。 那么当类库的静态变量发生变化后,例如:    public const int MAX_VALUE = 15;       那么对于调用端程序是可以在没有重新编译的情况下进行运行,不过此时程序的中间语言代码对应于静态变量的值是10,而不是新类库中的15。因此这样产生的不一致,程序会引发潜在的bug。解决此类问题的方法,就是调用端程序在更新类库之后重新编译一下,即生成新的中间语言代码。   对于如上在const定义常量时所存在的潜在bug,在用readonly定义常量时是不会发生的。因为readonly定义的常量类似于类的成员,因此在访问的时候需要根据具体常量地址来访问,从而避免此类bug。
  鉴于此,本书建议用readonly来替换const去定义常量。

C#箴言:定义常量的两种方法的更多相关文章

  1. 在C++中定义常量的两种方法的比较

    常量是定以后,在程序运行中不能被改变的标识符.C++中定义常量可以用#define .const 这两种方法.例如:#define PRICE 10 //定义单价常量10const int PRICE ...

  2. C#定义常量的两种方法

    在C#中定义常量的方式有两种,一种叫做静态常量(Compile-time constant),另一种叫做动态常量(Runtime constant).前者用“const”来定义,后者用“readonl ...

  3. spring boot 学习10 定义springboot的两种方法

    使用spring boot的两种方法: A:继承spring-boot-starter-parent项目 这种方式很简单,只需要在POM里面添加parent父工程即可. B: 如果你不喜欢继承spri ...

  4. Apacheserver自己定义404页面的两种方法以及.htaccess的重要命令总结

    Apacheserver自己定义404错误页面有两种方法: 第一种方法最简单,直接在Apache的httpd.conf下进行配置改动命令,改动的内容请參看.htaccess命令写法中的自己定义错误页面 ...

  5. Delphi Windows API判断文件共享锁定状态(OpenFile和CreateFile两种方法)

    一.概述 锁是操作系统为实现数据共享而提供的一种安全机制,它使得不同的应用程序,不同的计算机之间可以安全有效地共享和交换数据.要保证安全有效地操作共享数据,必须在相应的操作前判断锁的类型,然后才能确定 ...

  6. WebGL中添加天空盒的两种方法

    天空盒 的添加可以让模型所在的场景非常漂亮,而其原理也是非常简单的,相信看完下面代码就可以明白了. 说到天空盒的两种方法,倒不如说是两种写法,分别用了纹理加载的两个方法:loadTexture和loa ...

  7. Maven使用第三方jar文件的两种方法

    转于http://blog.csdn.net/youhaodeyi/article/details/1729116 主要用于回查与标记 在Maven中,使用第三方库一般是通过pom.xml文件中定义的 ...

  8. Kettle_设置变量的两种方法

    一个复杂的kettle作业一般包括很多子作业和转换,在主作业Start后通常会添加一个[设置变量]的流程,该流程的功能是为所有流程的公共变量设置通用值.       主作业添加的[设置变量]针对的是所 ...

  9. Loadrunner 接口测试的两种方法

    其实无论用那种测试方法,接口测试的原理是通过测试程序模拟客户端向服务器发送请求报文,服务器接收请求报文后对相应的报文做出处理然后再把应答报文发送给客户端,客户端接收应答报文这一个过程. 方法一.用Lo ...

随机推荐

  1. UVA 12130 - Summits(BFS+贪心)

    UVA 12130 - Summits 题目链接 题意:给定一个h * w的图,每一个位置有一个值.如今要求出这个图上的峰顶有多少个.峰顶是这样定义的.有一个d值,假设一个位置是峰顶.那么它不能走到不 ...

  2. httpclient4 模拟访问网页 模拟登录 简单例子

    JAVA后台模拟登录一个网站,获得一定权限后进一步操作. 所用的工具: Apache HttpComponents client 4.3版本 以下为代码: import org.apache.http ...

  3. Java实现MD5加密解密类

    http://blog.csdn.net/m_changgong/article/details/4361526

  4. 使用MSSQL同步&发布数据库快照遇到错误:对路径“xxxxx”访问被拒绝的解决方法

    使用MSSQL同步 数据库同步做后后测试:先在同步那台服务器(服务器A)数据库里修改里面数据库,然后再去被同步那台服务器(服务器B)看下数据有没被同步过去 发布数据库快照遇到错误:对路径“xxxxx” ...

  5. Python pandas 获取Excel重复记录

    pip install pandas pip install xlrd 大量记录的时候,用EXCEL排序处理比较费劲,EXCEL程序动不动就无响应了,用pands完美解决. # We will use ...

  6. linux shell执行远程计算机上的命令或者脚本(ssh)

    大数据平台下经常建立设计多个节点的集群需要统一部署,这就设计到守护进程或者部署脚本在不同节点执行,如果能在master机器上,统一执行脚本,一次性启动整个集群的服务,感觉很nice.因为,分享如下内容 ...

  7. Boost智能指针——scoped_ptr

    boost::scoped_ptr和std::auto_ptr非常类似,是一个简单的智能指针,它能够保证在离开作用域后对象被自动释放. 上一段代码,以及其输出: #include <string ...

  8. iOS 判定string是不是中文字符

    +(BOOL)IsChinese:(NSString *)str { ; i< [str length];i++) { int a = [str characterAtIndex:i]; if( ...

  9. "php"正则表达式使用总结

    一直对php的正则表达式的理解不是很深刻,而且是很一知半解,所以把自己用的的正则表达式总结下,以后方便查阅,以后遇到正则表达式的时候然后再追加到该文档的后面: /** * php常用正则表达式 * p ...

  10. Codeforces 724C Ray Tracing 扩展欧几里得

    吐槽:在比赛的时候,压根就没想到这题还可以对称: 题解:http://blog.csdn.net/danliwoo/article/details/52761839 比较详细: #include< ...