C#基础 [12] 成员常量和只读字段
一、成员常量
1.常量
常量是在编译时已知并在程序的生存期内不发生更改的不可变值。常量使用 const 修饰符进行声明。只有 C# 内置类型(System.Object 除外)可以声明为 const,用户定义的类型(包括类、结构和数组)不能为 const。常量分为成员常量和本地常量。
2.成员常量
成员常量就是声明在类中的常量,它与前面讲过的本地常量相似,只是作用域不同:本地常量只存在方法中,而成员常量存在于类当中。
下面是一个声明成员常量的示例,MyCalendar类中包含一个成员常量months:
1 class MyCalendar 2 { 3 // 声明一个成员常量 4 public const int months = 12; 5 }
成员常量有如下特征:
1).成员常量使用const关键字声明,并且可以有修饰符(默认为private)。这一点在上例中已经得到了证明。
2).成员常量必须在声明的时候初始化。试图声明一个没有初始化表达式的成员常量将会得到如下图所示的错误提示:
3).成员常量的值在初始化之后是不可改变的,即使是在类内部也不行。在上面的示例中,常量 months 始终为 12,不可更改。实际上,当编译器遇到 C# 源代码(例如 months)中的常量修饰符时,将直接把文本值替换到它生成的中间语言 (IL) 代码中。因为在运行时没有与常量关联的变量地址,所以 const 字段不能通过引用传递,并且不能在表达式中作为左值出现。在代码中强行修改常量值,编译器将会提示如下图所示的错误消息:
4).在一条语句中可以同时声明多个相同类型的常量。
1 // 同时声明多个int型成员常量 2 const int months = 12, weeks = 52, days = 365;
5).用于初始化一个常量的表达式可以引用另一个常量。例如,下面的成员常量声明引用了上面已经声明的常量。
1 // 在声明常量时,可以引用已经声明的常量 2 const double daysPerWeek = (double)days / (double)weeks; 3 const double daysPerMonth = (double)days / (double)months;
6).常量就像静态变量。因为常量值对该类型的所有实例是相同的,所以成员常量被当作 static 字段一样访问。未包含在定义常量的类中的表达式必须使用类名、一个句点和常量名来访问该常量。例如:
1 // 使用类名访问成员常量 2 var m = MyCalendar.months;
7).不能声明静态常量。虽然常量与静态字段的访问方式一样,但是不能声明static常量。因为常量与真正的静态字段不同:静态字段有存储位置,而常量没有自己的存储位置,常量在编译时被编译器替换为了与声明类型一致的字面量。下面是上面的months常量反编译为IL语言之后的代码:
1 // 成员常量已经被替换为了整型字面量(literal) 2 .field public static literal int32 months = int32(12)
声明static常量将会得到下图所示的错误提示:
二、只读字段
可以使用readonly修饰符声明只读字段。readonly 关键字是可以在字段上使用的修饰符。当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者出现在同一类的构造函数中。
1 class MyAge 2 { 3 // 声明一个只读字段,在声明的同时初始化 4 readonly int _year = 1; 5 6 // 构造函数 7 MyAge(int year) 8 { 9 // 在构造函数中改变只读字段的值 10 _year = year; 11 } 12 void ChangeYear() 13 { 14 //_year = 1967; // 在初始化和构造函数之外,不可改变readonly字段的值. 15 } 16 }
三、成员常量和只读字段不同
1.const字段只能在声明语句中初始化,而且必须初始化,初始化之后在任何地方都不能改变;readonly字段既可以在声明时初始化,也可以在构造函数中改变它的值:如果是实例只读字段,可以在实例构造函数中改变它的值,如果是静态只读字段,则可以在静态构造函数中改变它的值。
2.const字段的值必须在编译器决定,编译完成之后它的值就被替换为字面量;readonly字段的值可以在运行时决定,可以在不同的构造函数中设置不同的值。
3.const总是像静态字段,在类的外部要通过"类名.常量名"的方式访问;readonly字段既可以是静态字段,也可以是实例字段。
4.const在内存中没有存储位置,而readonly字段在内存中有存储位置。
参考:成员常量:http://msdn.microsoft.com/zh-cn/library/ms173119(VS.100).aspx
只读字段:http://msdn.microsoft.com/zh-cn/library/acdd6hb7(VS.100).aspx