const和static readonly的區別

來源:互聯網
上載者:User
const
用於修改欄位或局部變數的聲明。它指定欄位或局部變數的值是常數,不能被修改。常量的值必須在編譯的時候確定,編譯後,CLR將常量的值儲存在Assembly的怨資料中。如果變數是const,那麼他隱式的是static的。因此在聲明常數的時候只需將該變數聲明為const即可,而不允許在聲明常數的時候使用static。
當代碼引用常量時,CLR在中繼資料中尋找該符號,將提取的常量值嵌入到IL中,所以常量沒有地址以及相應的分配記憶體,而且不能通過引用傳遞變數

readonly
在欄位上使用的修飾符,表示該欄位是唯讀。當一個欄位在聲明為readonly的時候,只有兩種方式可以對其賦值,即作為聲明的一部分出現,或者在同一類的建構函式中。
對於執行個體欄位,在包含欄位聲明的類的執行個體建構函式中;或者,對於靜態欄位,在包含欄位聲明的類的靜態建構函式中。也只有在這些上下文中,將 readonly 欄位作為 out 或 ref 參數傳遞才有效。

static
聲明屬於類型本身而不是屬於特定對象的靜態成員,可用於類、欄位、方法、屬性、運算子、事件和建構函式,但不能用於索引器、解構函式或類以外的類型。
儘管類的執行個體包含該類所有執行個體欄位的單獨副本,但每個靜態欄位只有一個副本
不能通過類的執行個體引用靜態成員,只可以通過類型名稱引用它
如果對類應用 static 關鍵字,則該類的所有成員都必須是靜態
類(包括靜態類)可以有靜態建構函式。在程式開始和執行個體化類之間的某個時刻調用靜態建構函式

const和readonly
const
1. 在編譯期間解析的常量
2. 必須在聲明就初始化
3. 既可用來修飾類中的成員,也可修飾函數體內的局部變數。
readonly
1. 在運行期間解析的常量,
2. 既可以在聲明時初始化也可以在構造器中初始化,因此根據使用的建構函式,readonly的欄位可能具有不同的值。
3. 只可以用於修飾類中的成員

const和static readonly
都表示靜態常量,賦值以後都不可以更改

我們都知道,const和static readonly的確很像:通過類名而不是對象名進行訪問,在程式中唯讀等等。在多數情況下可以混用。
二者本質的區別在於,const的值是在編譯期間確定的,因此只能在聲明時通過常量運算式指定其值。而static readonly是在運行時計算出其值的,所以還可以通過靜態建構函式來賦值。
明白了這個本質區別,我們就不難看出下面的語句中static readonly和const能否互換了:
1. static readonly MyClass myins = new MyClass();
2. static readonly MyClass myins = null;
3. static readonly A = B * 20;
   static readonly B = 10;
4. static readonly int [] constIntArray = new int[] {1, 2, 3};
5. void SomeFunction()
    {
      const int a = 10;
       ...
    }

1:不可以換成const。new操作符是需要執行建構函式的,所以無法在編譯期間確定
2:可以換成const。我們也看到,Reference類型的常量(除了String)只能是Null。
3:可以換成const。我們可以在編譯期間很明確的說,A等於200。
4:不可以換成const。道理和1是一樣的,雖然看起來1,2,3的數組的確就是一個常量。
5:不可以換成readonly,readonly只能用來修飾類的field,不能修飾局部變數,也不能修飾property等其他類成員。

因此,對於那些本質上應該是常量,但是卻無法使用const來聲明的地方,可以使用static readonly。例如C#規範中給出的例子:

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue = new Color(0, 0, 255);static readonly需要注意的一個問題是,對於一個static readonly的Reference類型,只是被限定不能進行賦值(寫)操作而已。而對其成員的讀寫仍然是不受限制的。

public static readonly MyClass myins = new MyClass();

myins.SomeProperty = 10;  //正常
myins = new MyClass();    //出錯,該對象是唯讀

但是,如果上例中的MyClass不是一個class而是一個struct,那麼後面的兩個語句就都會出錯。

 

    private byte red, green, blue;

    public Color(byte r, byte g, byte b)
     {
         red = r;
         green = g;
         blue = b;
     }
}

C#擁有兩種不同的常量: 靜態常量(compile-time constants)和動 態常量(runtime constants)。它們有不同的特性,錯誤的使用不僅會損失效率,還可能造成錯誤。相比之下,靜態常量在速度上會稍稍快一些,但是靈活性卻比動態常量差很多。

//靜態常量(隱式是靜態)
public const int compiletimeConstant = 1;
//動態常量
public static readonly runtimeConstant = 1;

      靜態常量在編譯時間會將其替換為所對應的值,也就是說下面這2句話通過編譯器編譯後產生的IL是一樣的。

//通過編譯後二者會被翻譯成相同的中繼語言
int myNum = compiletimeConstant;
int myNum = 1;

      動態常量的值是在運行時獲得的。IL中將其標為唯讀常量,而不是用常量的值代替。

      靜態常量只能被聲明為簡單的資料類型(內建的int和浮點型)、枚舉或字串。下面的程式段是通不過編譯的。你不能用new關鍵字初始化一個靜態常量,即便是對一個實值型別來說。

//這樣是錯誤的
public const DateTime myDateTime = new DateTime(2006,9,1,0,0,0);
//這樣是可以的
public static readonly DateTime myDateTime = new DateTime(2006,9,1,0,0,0);

       唯讀資料也是常量的一種,它們不能在構造器初始化之後被修改。但是它同靜態常量不同,它的值是在運行時才被指派的,因此就會獲得更大的靈活性。動態常量可以是任意的資料類型。

       二者最大的差別在於:靜態常量在編譯時間會將其換為對應的值,這就意味著對於不同的程式集來說,當你改變靜態常量的時候需要將其重新編譯,否則常量的值不會發生變化,可能引發潛在的問題,而動態常量就不會有這種情況。

     用const定義的常量(隱式是靜態),需要像訪問靜態成員那樣去訪問const定義的常量,而用對象的成員方式去訪問會出編譯錯誤。 聲明的同時要設定常量值。
      從另一方面來說,如果你的確要聲明一些從不改變且處處唯一的常量,例如鉤子函數SetWindowsHookEx的idHook參數或序列化時的版本等,就應該使用靜態常量。但是用到這樣的常量的機會不多。一般來說我們應該使用靈活性更高的動態常量。

               靜態常量            動態常量

記憶體消耗        無                   因為要儲存常量 有消耗

初始化          很少的簡單類型,     任意類型,可以在類建構函式中賦值
                不能new,必須在
                聲明同時賦值

何時發揮作用   編譯時間進行替換       相當於類中的資料成員

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.