第二遍文章我打算把const和readonly的區別拿出來講下,因為寫代碼這么久我都還沒搞清楚這兩者的區別,實在有點慚愧,所以這一次我打算搞清楚它。
定義
來看看MSDN的解釋:
readonly:readonly關鍵字是可以在字段上使用的修飾符。當字段聲明包括readonly修飾符時,該聲明引入的字段賦值只能作為聲明的一部分,或者出現在同一類的構造函數中。
const:使用 const 關鍵字來聲明某個常量字段或常量局部變量。 常量字段和常量局部變量不是變量並且不能修改。
太多理論的講解有些人可能看了更犯暈,所以直接寫些代碼我覺得可能比較直觀好理解。
舉例
我們先來看下const
public class ConstTest { class SampleClass { public int x; public int y; public const int c1 = 5; public const int c2 = c1 + 5; public static const int z=8; //這個寫法錯誤,因為const是靜態常量,可看下面提供c1的IL語言圖片。
//變量可以在這里初始化值,但是如果把const放在這里初始化,編譯會出錯(賦值號左邊必須為變量、屬性或索引器) public SampleClass(int p1, int p2) { x = p1; y = p2; } } static void Main() { SampleClass mC = new SampleClass(11, 22); Console.WriteLine("x = {0}, y = {1}", mC.x, mC.y); Console.WriteLine("c1 = {0}, c2 = {1}",SampleClass.c1, SampleClass.c2); //類型引用 } }
/* Output x = 11, y = 22 c1 = 5, c2 = 10 */
來看下IL語言:
c2和y省略在這里省略,從上面的圖我們得出了一個結論:
那就是靜態常量,那什么是靜態常量呢?靜態常量是指編譯器在編譯時候會對常量進行解析,並將常量的值替換成初始化的那個值。即圖中里面的c1和c2,它們都是在編譯的時候值就確定下來(c1=5,c2=10),這個相信大家也比較好理解。
我們再來看readonly:
public class ReadOnlyTest { class SampleClass { public readonly int x; public readonly int y = 25; public static readonly int z=12;
//無參構造函數初始化readonly常量 public SampleClass() { y = 24; }
//靜態無參構造函數內初始化static readonly常量 static SampleClass() { z = 23; }
//有參構造函數初始化readonly常量 public SampleClass(int p1, int p2) { x = p1; y = p2; } } static void Main() { //訪問靜態成員 Console.WriteLine(SampleClass.z); //訪問非靜態成員 SampleClass p1 = new SampleClass(11, 21); // OK Console.WriteLine("p1: x={0}, y={1}", p1.x, p1.y); SampleClass p2 = new SampleClass(); Console.WriteLine("p2: x={0}, y={1}", p2.x, p2.y); Console.ReadKey(); } }
/* Output: 23
p1: x=11, y=21
p2: x=0, y=24
*/
同樣的,來看IL語言:
我們先看下什么是動態常量:
動態常量,是指值在運行的那一刻才獲得的,編譯器編譯期間將其標示為只讀常量,而不用常量的值代替,這樣動態常量不必在聲明的時候就初始化,而可以延遲到構造函數中初始化。
通過const和readonly的代碼我們可以得出以下結論:
1.readonly和static readonly定義的常量,指定初始值后(包括在構造函數內指定初始值)將不可更改,可讀不可寫。
2.static readonly常量,如果在構造函數內指定初始值,則必須是靜態無參構造函數,例如z參數的初始化過程。
3.const和static readonly定義的常量是靜態的,只能由類型直接訪問;而readonly定義的常量是非靜態的,只能由實例對象訪問。
const和readonly比較
1.const默認是靜態的,只能由類型訪問,不能和static同時使用,否則編譯錯誤;readonly默認是非靜態,由實例對象來訪問,可以顯式使用static定義為靜態成員。
2.const只能引用在值類型和string類型上,其他引用類型常量必須聲明為null,否則以new為const引用類型常量賦值,編譯器會提示錯誤,原因是構造函數初始化在運行時,而非編譯時;readonly只讀字段可以是任意類型,但是對於引用類型字段來說,readonly不能限制對該對象實例成員的讀寫控制。
3.const必須在字段聲明時初始化;而readonly可以在聲明時,或者構造函數中進行初始化,不同的構造函數可以為readonly常量實現不同的初始值
4.const可以定義字段和局部變量;而readonly則只能定義字段
5.const由於是靜態常量所以在編譯時會對常量進行解析,而readonly是動態常量在編譯期間編譯器將其標示為只讀常量,而不用常量的值代替,這樣就不必在聲明的時候就初始化,而可以延遲到構造函數中初始化
6.從應用角度來看,對於恆定不變且單獨使用的量來說,應該考慮聲明為const常量,例如性能比,百分比等;而對於可能隨實際運行發生變化的量,應該考慮聲明readonly常量,例如日期或時間,數據庫中的主鍵id等
以上內容希望對一些朋友帶來幫助~~~