在声明字段时,可以使用readonly关键字声明一个动态常量。readonly 关键字不同于 const 关键字。 const 字段只能在该字段的声明中初始化。 可以在字段声明和任何构造函数中多次分配 readonly 字段的值。 因此,根据所使用的构造函数,readonly 字段可能具有不同的值。但是,采用readonly修饰的字段或变量,也仅仅在声明时赋值或构造函数中赋值这两种途径

使用格式

readonly 数据类型 字段名/变量量 = 值;

观察下面的例子

public class Math
 
 {
 
     public  readonly double PI = 0;
 
     public Math()
 
     {
 
         PI = 3.1415926;
 
     }
 
     void Change()
 
     {
 
         PI = 0;
 
         /* 错误:无法分配到只读字段
 
          * (除非在定义了该字段的类型的构造函数
 
          * 或 init-only 资源库中,
 
          * 或者在变量初始值设定项中)
 
          */            
 
     }
 
 }

我们在类型Math中声明了一个只读字段PI,同时赋值为0,然后在构造函数中将PI的值改成3.1415926,这都是合法的。最后,在Change成员中再次将PI改成0时,编译器会引发一个错误,导致源代码无法编译。这个错误的提示就是:CS0191 无法分配到只读字段(除非在定义了该字段的类型的构造函数或 init-only 资源库中,或者在变量初始值设定项中)

所以,readonly修饰的字段,只有两种途径可以赋值。

另外,如果将PI定义成一个静态只读的字段,这个连构造函数中都不能修改其值,否则将引发如下错误:CS0198 无法对静态只读字段赋值(静态构造函数或变量初始值中除外)。除非在静态构造函数中去修改值。

readonly动态常量_构造函数

正确的做法如下:

public class Math
 
 {
 
     public static readonly double PI = 0; //静态字段
 
     static Math() //静态构造函数
 
     {
 
         PI = 3.1415926;
 
     }
 
 }
 
  
 
 internal class Program
 
 {       
 
     static  void Main(string[] args)
 
     {
 
         Console.WriteLine($"PI = {Math.PI}");        
 
         Console.ReadKey();
 
     }
 
 }

输出结果

PI = 3.1415926

总结如下

项目

const静态常量

readonly动态常量

定义

声明的同时要设置常量值。

声明的时候可以不需要进行设置常量值,可以在类的构造函数中进行设置。

类型限制

只能修饰基元类型,枚举类型或者字符串类型。

没有限制,可以用它定义任何类型的常量。

对于类对象而言

对于所有类的对象而言,常量的值是一样的。

对于类的不同对象而言,常量的值可以是不一样的。

内存消耗


要分配内存,保存常量实体。

综述

性能要略高,无内存开销,但是限制颇多,不灵活。

灵活,方便,但是性能略低,且有内存开销。

表1 const和readonly的区别

  • const修饰的常量在声明的时候必须初始化;readonly修饰的常量则可以延迟到构造函数初始化 。
  • const常量既可以声明在类中也可以在函数体内,但是static readonly常量只能声明在类中。
  • const是静态常量,所以它本身就是static的,因此不能手动再为const增加一个static修饰符。
  • const修饰的常量在编译期间就被解析,即:经过编译器编译后,我们都在代码中引用const变量的地方会用const变量所对应的实际值来代替; readonly修饰的常量则延迟到运行的时候。

当前课程源码下载:(注明:本站所有源代码请按标题搜索)
文件名:047-readonly动态常量.zip
链接:https://pan.baidu.com/s/1Bq2lX7cruUbklLwgjGggSw
提取码:byte

——重庆教主 2024年1月24日