转:《Effective C#》Item 2:定义常量的两种方法

转载 2007年09月30日 10:27:00

转:http://writeblog.csdn.net/PostEdit.aspx

 

在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来定义常量的时候,在类型上有很多限制。首先,此类型必须属于值类型或者String类型,同时此类型的初始化不能通过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#箴言:定义常量的两种方法

  • 2011年08月22日 14:19
  • 27KB
  • 下载

C#中定义常量的两种方法

原文地址:C#中定义常量的两种方法作者:在C#中定义常量的方式有两种,一种叫做静态常量(Compile-time constant),另一种叫做动态常量(Runtime constant)。前者用“c...

C# 定义常量的两种方法

转自:http://dev.yesky.com/msdn/423/2438923.shtml 在C#中定义常量的方式有两种,一种叫做静态常量(Compile-time constant),另一种叫做...

Effective Modern C++ Item 7 总结:关于两种对象创建方法“()、{}”的区分

在用大括号进行初始化的时候有两个例外: 例外1. 空大括号意味着无参,而不是空的std::initializer_list. 在对象的定义中会调用类的无参构造函数。 例如有如下类定义: class W...
  • Jxianxu
  • Jxianxu
  • 2017年04月17日 09:56
  • 160

Effective C# Item19:定义并实现接口优于继承类型

这个话题不仅仅是针对.NET的,在其他面向对象语言的环境中,例如Java,都会有接口和抽象类,对于究竟是选择接口还是抽象类,已经有了太多的讨论,包括设计模式中都有了一条设计原则:组合优于继承,虽然这条...

【Effective Java】Ch2_创建销毁对象:Item7_避免使用finalize方法

Finalizer通常是不可预测的、危险的、不必要的。使用finalizer会导致不稳定的行为、低下的性能、以及可移植问题。Finalizer也有其可用之处,本文稍后会做介绍,但是作为一个首要法则,你...

【Effective Java】Ch2_创建销毁对象:Item1_考虑用工厂方法替代构造函数

本章的主题是创建和销毁对象:何时创建、怎样创建;何时应该避免创建、如何避免创建;如何确保对象适时被销毁;如何管理对象销毁前的清理动作。         一个类如果要允许客户获得其实例,常用方法是提...

[Effective Java Distilled] Item 2 当构造方法中有多个参数时,考虑建造者模式

关于Effective Java Distilled: 《Effective Java》这本书我断断续续的读了近两遍,里面的内容挺有深度,对提高工程代码质量也非常有帮助。我打算慢慢的整理出来一个...

C# 字符串反转(两种方法)

  • 2010年03月17日 16:52
  • 15KB
  • 下载

Effective C# Item24:声明式编程优于命令式编程

声明式编程是一种更简单、更精练的描述软件程序行为的方式,它意味着可以使用声明、而非指令的方式来定义程序的行为。C#中大部分编程都是命令式编程,即通过编写方法来定义程序的行为。我们可以通过使用特性,来在...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:转:《Effective C#》Item 2:定义常量的两种方法
举报原因:
原因补充:

(最多只允许输入30个字)