2016-03-03 58 views
3

我已經在C#中工作了8個月左右所以請原諒我,如果這是愚蠢的......Enum.GetName()作爲不變的性質

我有一個枚舉,我需要字符串值的幾倍類。所以我想使用Enum.GetName()將它設置爲一個沒有問題的字符串變量。我只是這樣做...

private string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name); 

它工作得很好。

但我試圖保護它好一點,因爲這個特定的枚舉比所有其他更重要,如果我不小心改變了字符串值,所以我試圖使它像這樣const。

private const string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name); 

我的眼睛,這似乎不錯,因爲都應該在編譯時是已知的。

但Visual Studio 2013引發錯誤,指出「無法解析符號GetName」。我知道它沒有標記爲「常量」時可以使用。

因此,這導致我有兩個關於這方面的問題? 爲什麼它沒有引用GetName枚舉? (經過一些研究,我懷疑這是GetName作爲一種方法,而不是Enum類的屬性,但錯誤信息對我來說並沒有意義)

最後是否有一種方法可以讀取MyEnum.Name的名稱改爲一個常量字符串,而不是我正在做的事情?

+1

可以使用Visual Studio 2015年呢?然後你可以使用'nameof' ... –

+1

「在我看來,這看起來很好,因爲它應該在編譯時都知道。」 - 只有編譯器知道'Enum.GetName'的作用,它不會......(就像它不知道'Math.Sqrt'是什麼一樣,所以'const double x = Math.Sqrt(2.0) ;'也不會編譯。) –

+0

@JonSkeet不幸的是,我們暫時必須堅持使用Visual Studio 2013,但是我將不得不考慮「nameof」,因爲我們將在2015年底之前進入2015年。 – DVS

回答

2

就讓它只讀:

private readonly string MyEnumString = Enum.GetName(typeof(MyEnum), MyEnum.Name); 

那麼就不能在事後改變。

您不能將調用方法的結果賦給常量; C#只是不允許它 - 編譯器必須在編譯時調用該方法,可能在編譯之前(並且不僅需要生成IL,還必須使用JIT編譯器來編譯IL)。

Enum.GetName(typeof(MyEnum), MyEnum.Name);正在調用一個方法,所以你不能將結果賦給一個常量。

[編輯]作爲喬恩斯基特在評論說上面,你可以,如果使用C#6或更高版本(即VS2015或更高版本)使用nameof:因爲這裏

private const string MyEnumString = nameof(MyEnum.Name); 

nameof作品你是不是調用一個任意方法,但是您使用編譯器功能來訪問類型的名稱。

+0

只讀是我正在尋找! – DVS

0

不能將方法的結果用作常量,因爲方法評估只能在運行時發生。必須在編譯時知道常量的值。爲了編譯器能夠評估該常量,它需要知道Enum.GetName的語義並在編譯時執行它,這是不可能的。

您可以改爲將其標記爲static readonly。這樣它就會被聲明的每種類型設置一次,並且在運行時不能再進行更改。

0

它甚至可能不會在運行時知:

MSDN

如果多個枚舉成員具有相同的基礎值,該GetName方法保證它會返回名稱這些枚舉成員之一。但是,並不保證它將始終返回相同枚舉成員的名稱。

(強調)

void Main() 
{ 
    Console.WriteLine (Enum.GetName(typeof(Test),Test.One)); 
} 

public enum Test 
{ 
    Zero, 
    One, 
    Two, 
    Uno = 1, 
    Dos = 2, 
} 

我一直得到上​​面的程序輸出Uno

原因是不知道是因爲枚舉被編譯爲底層的。上面的調用基本上編譯爲Enum.GetName(typeof(Test), 1)GetName尋找具有該值的成員來查找名稱。它如何做,顯然是一個實現細節,可能不會產生一致的結果。

可以使用在C#6恆定的,後來是nameof什麼:

private const string MyEnumString = nameof(MyEnum.Name);