C# readonly和const
阿新 • • 發佈:2020-06-18
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 readonlyint 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個建議》陸敏技