我知道枚舉被編譯爲常量,所以改變它們會導致重大更改。我想知道的是爲什麼不是枚舉編譯靜態只讀變量相同的方式呢?爲什麼枚舉編譯爲常量而不是靜態值?
回答
它們可以比字段更高效,所以當它們可以直接嵌入到IL中時,不需要以相同的方式編譯它們。
[Enums]加載的方式與加載const值的方法相同 。它們直接嵌入到IL中。另一方面,字段需要一個現場加載指令 (ldsfld),這會稍微影響性能。因此在典型用法中,枚舉因此爲 與const一樣快;字段有點慢。
(Source)
好吧,這幾乎是一個基於性能的決定。這正是我所尋找的......「爲什麼?」的答案。 – 2011-12-30 14:23:27
是的。問題是「爲什麼他們編譯爲常量而不是靜態只讀?」 ......基本上,設計決定是使它們成爲常量文字而不是靜態只讀? – 2011-12-30 05:12:35
@my,如果我沒有弄錯只讀可以在Instantiation中設置,並且不可以在實例化中設置的常量 – 2011-12-30 05:24:54
兩個給出的答案在技術上是正確的,但錯過了用靜態差分常量的解釋(只讀)。在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
}
}
真棒解釋,花花公子 – ivowiblo 2011-12-30 06:19:17
是的,但問題不在於爲什麼枚舉打破了變化,但爲什麼微軟選擇將它們編譯爲常量而不是靜態只讀字段。他們本來可以讓編譯器以任何方式進行,問題是爲什麼他們用常量去做,而不是爲了改變性能,而有人回答它......僅僅是爲了提高性能。 – 2011-12-30 14:25:43
- 1. 爲什麼使用枚舉而不是帶有靜態常量的類?
- 2. 爲什麼要使用枚舉而不是常量?
- 3. 爲什麼使用靜態「常量」而不是實際值?
- 4. 爲什麼使用靜態枚舉?
- 5. 爲什麼Phobos使用枚舉常量?
- 6. 爲什麼編譯器不會抱怨錯誤枚舉值
- 7. 爲什麼不是由C編譯器檢查的枚舉?
- 8. 爲什麼NSString編碼常量是作爲變量而不是枚舉實現的?
- 9. Java枚舉與靜態常量
- 10. 爲什麼Java不允許開啓靜態枚舉?
- 11. 爲什麼JNI在枚舉中找不到自定義靜態?
- 12. 爲什麼使用字符串常量與枚舉常量?
- 13. 爲什麼這個Java枚舉代碼不能編譯?
- 14. 爲什麼這個枚舉不能編譯?
- 15. Java7/WatchEvent - 爲什麼它不是枚舉?
- 16. 爲什麼`std :: byte`是一個枚舉類而不是類?
- 17. 說明int枚舉模式是編譯時常量是什麼意思?
- 18. Java枚舉,靜態類變量 - 爲什麼我不能這樣做?
- 19. 爲什麼Java枚舉常量初始化不完整?
- 20. 爲什麼枚舉包括可枚舉
- 21. 枚舉拋出concurrentModification異常。爲什麼?
- 22. Java枚舉變量是靜態的嗎?
- 23. 枚舉值是什麼?
- 24. 爲什麼我們在枚舉中寫入Integer而不是int?
- 25. 的Java枚舉 - 爲什麼使用的toString,而不是名稱
- 26. 爲什麼編譯器生成的枚舉器「yield」不是結構體?
- 27. PropertyInfo.GetValue返回枚舉常量的名稱,而不是價值
- 28. 這是爲什麼用「Is」編譯而不用「IsNot」編譯?
- 29. 爲什麼我們訪問枚舉值::
- 30. 爲什麼強制類型枚舉編譯爲「不在枚舉範圍內」的int?
枚舉值不能在運行時更改,方法與const的相同。如果它們是靜態的,那意味着它們的價值可能會改變。 – 2011-12-30 04:31:25