2011-12-30 129 views
5

我知道枚舉被編譯爲常量,所以改變它們會導致重大更改。我想知道的是爲什麼不是枚舉編譯靜態只讀變量相同的方式呢?爲什麼枚舉編譯爲常量而不是靜態值?

+1

枚舉值不能在運行時更改,方法與const的相同。如果它們是靜態的,那意味着它們的價值可能會改變。 – 2011-12-30 04:31:25

回答

6

它們可以比字段更高效,所以當它們可以直接嵌入到IL中時,不需要以相同的方式編譯它們。

[Enums]加載的方式與加載const值的方法相同 。它們直接嵌入到IL中。另一方面,字段需要一個現場加載指令 (ldsfld),這會稍微影響性能。因此在典型用法中,枚舉因此爲 與const一樣快;字段有點慢。

Source

+0

好吧,這幾乎是一個基於性能的決定。這正是我所尋找的......「爲什麼?」的答案。 – 2011-12-30 14:23:27

1

enum (C# Reference)

正如任何恆定,到 枚舉的各個值的所有參考文獻都在編譯時轉換爲數字文字

所以我錯過了什麼?

+0

是的。問題是「爲什麼他們編譯爲常量而不是靜態只讀?」 ......基本上,設計決定是使它們成爲常量文字而不是靜態只讀? – 2011-12-30 05:12:35

+0

@my,如果我沒有弄錯只讀可以在Instantiation中設置,並且不可以在實例化中設置的常量 – 2011-12-30 05:24:54

8

兩個給出的答案在技術上是正確的,但錯過了用靜態差分常量的解釋(只讀)。在C#中,常量總是比只讀更快,原因很簡單,用一個小的代碼示例最好的表達:

const int MyConstant = 10; 
static readonly int MyReadonly = 20; 

static void Main() 
{ 
    int result = MyConstant + MyReadonly; 
    // the above statement will be resolved to: 
    // int result = 10 + MyReadonly 
} 

在編譯時,編譯器取代以恆定的所有引用與常量的實際值。它可以這樣做,因爲常量必須在編譯時進行預定義。這與靜態只讀值不同,靜態只讀值雖然是靜態的,但實際上是在運行時解決的。看看下面的例子:

static readonly Encoding = Encoding.GetEncoding("GB2132"); 

有沒有辦法讓編譯器知道如果GB2132在此代碼是爲了運行機器上實際存在。解決此值的唯一方法是在運行時。靜態確保值本身不綁定到實例的生命週期,並且只讀確保只能設置一次該值。編譯器沒有辦法讓編譯器在編譯時替換對該字段的引用,因爲該值無法被知道。

邏輯上,只有基元類型可以標記爲常量。

現在在枚舉的情況下,它非常簡單。枚舉只不過是帶有標籤的整數值。所以下面的代碼:

enum MyEnum 
{ 
    First, 
    Second, 
    Third 
} 

static void Main() 
{ 
    MyEnum test = MyEnum.First; 

    if (test == MyEnum.Second) 
    { 
     // whatever 
    } 
} 

會被編譯器解析爲:

const int MyEnum_First = 0; 
const int MyEnum_Second = 1; 
const int MyEnum_Third = 2; 

static void Main() 
{ 
    int test = MyEnum_First; 

    if (test == MyEnum_Second) 
    { 
     // whatever 
    } 
} 

這反過來意味着恆領域實際的引用可以在編譯時已知值替換,使得代碼的最終版本如下所示:

static void Main() 
{ 
    int test = 0; 

    if (test == 1) 
    { 
     // whatever 
    } 
} 
+0

真棒解釋,花花公子 – ivowiblo 2011-12-30 06:19:17

+0

是的,但問題不在於爲什麼枚舉打破了變化,但爲什麼微軟選擇將它們編譯爲常量而不是靜態只讀字段。他們本來可以讓編譯器以任何方式進行,問題是爲什麼他們用常量去做,而不是爲了改變性能,而有人回答它......僅僅是爲了提高性能。 – 2011-12-30 14:25:43

相關問題