常量和字段
?? ? ?定义常量符号时,它的值必须能在编译时确定。确定之后,编译器将常量的值保存到程序集的元数据中。这意味着只能为编译器认定的基元类型定义常量。在C#中,以下类型都是基元类型,可以定义常量:Boolean、Char、Byte、SByte、Int16、UInt16、Int32、UInt32、Int64、UInt64、Single、Double、Decimal、String。
?? ? ?由于常量的值从不变化,所以常量总被视为类型定义的一部分。换言之,常量总被视为静态成员。
?? ? ?代码引用一个常量符号时,编译器会在定义常量的程序集的元数据中查找该符号,提取常量的值,并将值嵌入生成的IL代码中。由于常量的值直接嵌入代码,所以在运行时不需要为常量分配任何内存。
?? ? ?将一下代码编译成一个DLL程序集
?? public sealed class SomeLibraryType{
?? public const Int32 MaxEntriesInList=50; ? //常量总是隐式为static
???}
?? ? ?然后再生成一个应用程序程序集
?? public sealed class Program{
?? public static void Main(){
?? ? Console.WriteLine(SomeLibraryType.MaxEntriesInList);
?? ? ?}
?? }
?? 编译器在生成应用程序代码时,会注意到MaxEntriesInList是一个值为50的常量符号,所以会将Int32值50嵌入应用程序的IL代码中。所以在生成应用程序程序集之后,运行时根本不会加载DLL程序集,可以把它从磁盘上删除。
?? 这个例子清晰的展示了版本控制的问题,如果开发人员将MaxEntriesInList的值更改为1000,并且只重新生成DLL程序集,那么应用程序程序集不会受到任何影响。应用程序要获得新值,也必须重新编译。 如果希望在运行时从一个程序集提取另一个程序集中的值,那么不应该使用常量,而应该使用readonly字段。
?
?? ? ?将上述DLL程序集改成如下
???public sealed class SomeLibraryType{
?? public static readonly Int32 MaxEntriesInList=50; ? //此处使用static是为了字段和类型关联
???}
??编译器在生成应用程序代码时,会加载DLL程序集,然后从分配给它的动态内存中提取MaxEntriesInList字段的值,而这时将不用重新编译应用程序程序集。
?
??当某个readonly字段是引用类型时,那么不可以改变的是引用,而非字段引用的对象。