C#箴言:定义常量的两种方法

C#箴言:定义常量的两种方法,第1张

C#箴言:定义常量的两种方法,第2张

C#中定义常量有两种方式,一种叫做编译时常量,另一种叫做运行时常量。前者由“const”定义,后者由“readonly”定义。

对于静态常数(编译时常数),它的写法如下:

public const int MAX _ VALUE = 10

为什么称之为静态常数?因为上面的语句可以这样理解(注:下面的写法是错误的,会造成编译错误。这里只是为了便于解释)。

公共静态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定义的常量相当于一个类的成员,所以当使用readonly定义常量时,使用const定义常量的类型限制将全部消失,即readonly可以定义任何类型的常量。

综上所述,至于比较,两者的区别如下。

编译时常量,动态常量
常量值应该在定义声明时设置。声明时不需要设置常数值,但是可以在类的构造函数中设置。
类型限制首先,类型必须属于值类型的范围,其值不能由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定义常量。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » C#箴言:定义常量的两种方法

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情