1. 程式人生 > WINDOWS開發 >C# readonly和const

C# readonly和const

const效率高,readonly更靈活

區別:

1、const是一個編譯期常量,readonly是一個執行時常量

2、const只能修飾基元型別、列舉型別或字串型別,readonly沒有限制

const天然就是static的,不能手動為const新增一個static修飾符:

static const int ConstValue = 100;//編譯錯誤:常量“ConstValue”不能標記為 static    

const效率高是因為經編譯後,在程式碼中引用const變數的地方會用const變數所對應的實際值來代替,如:

1  Console.WriteLine(ConstValue);
2 Console.WriteLine(100);
    IL_0000: nop
    IL_0001: ldc.i4.s  100
    IL_0003: call      void [mscorlib]System.Console::WriteLine(int32)
    IL_0008: nop
    IL_0009: ldc.i4.s  100
    IL_000B: call      void [mscorlib]System.Console::WriteLine(int32)

第一行程式碼和第二行程式碼生成的IL程式碼時一致的。

readonly變數時執行時變數,其賦值行為發生在執行時,它在第一次賦值後將不可改變:

1)對於值型別變數,值本身不可改變。

2)對於引用型別變數,引用本身(相當於指標)不可改變。

例1:readonly修飾值型別變數

 1     static void Main(string[] args)
 2     {
 3         Student student = new Student(18);//傳值18
 4         student.age = 20;//編譯不通過,無法對只讀的欄位賦值(建構函式或變數初始值指定項中除外)    
 5     } 
 6 
 7     class Student
 8     {
 9         public readonly
int age; 10 public Student(int value) 11 { 12 age = value;//給只讀變數賦值18 13 } 14 }

student例項在構造方法對只讀變數age進行賦值,賦值後不可改變,所以第4行程式碼編譯不通過。

例2:readonly修飾引用型別編寫

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Sample sample = new Sample(new Student(18));
 6             sample.student.age = 20;//編譯通過,允許修改age
 7             //sample.student = new Student(20);//編譯不通過,無法對只讀的欄位賦值(建構函式或變數初始值指定項中除外)
 8         }
 9     }
10     class Sample
11     {
12         public readonly Student student;
13         public Sample(Student value)
14         {
15             student = value;
16         }
17     }
18     class Student
19     {
20         public int age;
21         public Student(int value)
22         {
23             age = value;//給只讀變數賦值18
24         }
25     }

因為引用本身不可變,所以第7行程式碼編譯不通過,指向的例項不可變;但是所指的例項的值卻是可以改變的,所以第6行程式碼編譯可以通過。

readonly所代表的執行時含義有一個重要的作用,就是可以為每個類的例項指定一個readonly變數。

例3:

 1     class Program
 2     {
 3         static void Main(string[] args)
 4         {
 5             Student student = new Student(18);
 6         }
 7     }
 8     class Student
 9     {
10         public readonly int age = 0;
11         public Student(int value)
12         {
13             age = value;
14         }
15     }

例3的程式碼是可以執行的,age首先在初始化時被初始化器賦值為0,然後,student例項化時,在構造方法中又被賦值為18。實際上,應該把初始化器理解成構造方法的一部分,它其實是一個語法糖。在構造方法內,可以多次對readonly賦值。

參考:《編寫高質量程式碼改善C#程式的157個建議》陸敏技