『框架设计(第2版)CLR Via C#』学习笔记——常量
常量之所以姓“常”,就是说它的值永远不会改变。定义一个常量符号时,它的值在编译时必须是确定的。编译后,常量的值就保存在程序集(assembly)的元数据中,这意味着它必须是编译器可以处理的基元数据(primitive type)。在C#中,可以用于定义常量的是:Boolen,Char,Byte,SByte,Int16,UInt16,Int32,UInt32,Int64,UInt64,Single,Double,Decimal和String。
常量总是被当作静态成员,而非实例成员。定义常量将导致元数据的产生。
using System; public sealed class SomeLibraryType{ public const Int32 MaxEntriesInList = 50; }
在上面的代码中要注意,c#不允许为常量指定static关键字,因为常量通常隐含着static。
当代码引用一个常量符号时,编译器将在定义常量的程序集的元数据中查找该符号,提取常量的值,并将值嵌入编译后生成的IL代码中。因为常量的值在编译时就直接嵌入代码中,所以在运行时就不需要为常量分配任何内存。
另外,我们还无法得到常量的地址,也不能通过引用传递常量。所以正是这样的约束导致常量没有很好的跨程序集版本控制特性。
让我们一起来看看为何会出现常量的版本控制问题。在程序集A中定义了一个常量i=50,编译它得到一个程序集。这时有一个程序集B引用了程序集A,并用到了A中的常量i,我们编译程序集B时,编译器读取A中i的值50,直接放到B中i出现的地方。也就是说当B编译后,B就只知道数字50,不知道它时怎么得来的,这时我们修订程序集A,把它的i修改为1000,然后我们编译程序集A得到新的程序集A,但是我们的B并不知道那个50已经改变了,所以如果B想要获取新值,也必须重新编译。
因此在运行时(不是在编译时),如果一个程序集需要另一个程序集中获取值,则不能使用常量,应当使用只读字段。