2010-04-16 77 views
279

可能重複:
Getting attributes of Enum’s value如何從值中獲取C#Enum描述?

我有描述一個枚舉的屬性是這樣的:

public enum MyEnum 
{ 
    Name1 = 1, 
    [Description("Here is another")] 
    HereIsAnother = 2, 
    [Description("Last one")] 
    LastOne = 3 
} 

我發現這段代碼的基礎上檢索說明Enum

public static string GetEnumDescription(Enum value) 
{ 
    FieldInfo fi = value.GetType().GetField(value.ToString()); 

    DescriptionAttribute[] attributes = 
     (DescriptionAttribute[])fi.GetCustomAttributes(
     typeof(DescriptionAttribute), 
     false); 

    if (attributes != null && 
     attributes.Length > 0) 
     return attributes[0].Description; 
    else 
     return value.ToString(); 
} 

這讓我寫這樣的代碼:

var myEnumDescriptions = from MyEnum n in Enum.GetValues(typeof(MyEnum)) 
         select new { ID = (int)n, Name = Enumerations.GetEnumDescription(n) }; 

我想要做的是,如果我知道枚舉值(例如1) - 我如何檢索描述?換句話說,我如何將一個整數轉換爲一個「枚舉值」傳遞給我的GetDescription方法?

+0

(!屬性= NULL)永遠是真實的,否則是多餘的。描述是System.ComponentModel – Jeff 2014-07-17 23:00:46

+1

。正是我想要的。我知道這會很簡單!現在,如果stackoverflow會讓我接受這個答案......它說我需要等待7分鐘。 – 2015-12-21 15:10:52

回答

277
int value = 1; 
string description = Enumerations.GetEnumDescription((MyEnum)value); 

默認在C#中的enum基礎數據類型爲int,你可以只投它。

+2

完美所需的命名空間爲 – davekaro 2010-04-16 01:52:16

+41

爲什麼我在.Net框架中找不到任何Enumerations類? – 2013-12-26 17:56:30

+53

Enumerations類是提問者自己寫的,GetEnumDescription()函數在問題中。 – 2013-12-29 17:03:46

5

你不能用通用的方式輕鬆做到這一點:你只能將整數轉換爲特定類型的枚舉。正如尼古拉斯所表明的,如果你只關心一種枚舉,那麼這是一個微不足道的表現,但是如果你想寫一個可以處理不同類型枚舉的泛型方法,事情會變得更復雜一些。你想沿着線的方法:

public static string GetEnumDescription<TEnum>(int value) 
{ 
    return GetEnumDescription((Enum)((TEnum)value)); // error! 
} 

但這會導致編譯器錯誤「詮釋不能轉換爲TEnum」(如果你解決這個問題,說:「TEnum不能轉換到Enum「)。因此,你需要通過插入管型騙過編譯器對象:

public static string GetEnumDescription<TEnum>(int value) 
{ 
    return GetEnumDescription((Enum)(object)((TEnum)(object)value)); // ugly, but works 
} 

您現在可以調用這個以獲取任何枚舉類型的描述就在眼前:

GetEnumDescription<MyEnum>(1); 
GetEnumDescription<YourEnum>(2); 
+0

如何「GetEnumDescription (1);」比GetEnumDescription((MyEnum)1)更好; ? – davekaro 2010-04-16 02:09:12

+0

@davekaro:像這樣實現,並不是那麼好,但基於泛型的更強大的實現可以在沒有顯式強制轉換的情況下執行此操作,因此如果該數字實際上不匹配任何枚舉值。 – Aaronaught 2010-04-16 02:15:46

+0

有趣。只是爲了澄清未來的讀者:如果數字不符合枚舉值之一(可以說「MyEnum value =(MyEnum)5;」,那麼一行就不會在明確的轉換中得到未處理的異常執行得很好,但你會在原始問題中實現GetEnumDescription()的第一行,因爲GetField()會返回null,因爲它找不到與該值匹配的字段)(爲了防止這種情況, d需要首先檢查Enum.IsDefined(),並返回null或一個空字符串,或者只是自己拋出一個ArgumentOutOfRangeException。) – 2010-04-16 02:48:22

68

我在實現這個通用的,類型安全的Unconstrained Melody方式 - 你會使用:

string description = Enums.GetDescription((MyEnum)value); 

此:

  • 確保(與泛型類型約束),該值確實是一個枚舉值
  • 避免了拳擊在當前解決方案
  • 緩存所有的描述,以避免使用在每次調用
  • 反射有一堆的其他方法,包括從描述

我認識的核心答案是剛剛從一個intMyEnum投解析值的能力,但如果你做了很多枚舉的工作,這是值得我們思考的使用約束旋律:)

+0

是不是「值」是一個整數?所以,Enums.GetDescription((MyEnum)值)只是將int轉換爲MyEnum? – davekaro 2010-04-16 12:20:12

+0

@davekaro:它將int轉換爲MyEnum - 但是你不能用任何非枚舉來調用它,包括一個「Enum」引用。基本上它就像你的代碼,但是有一些泛型魔術 – 2010-04-16 13:06:20

+1

@JonSkeet我在枚舉中看不到這種方法s.cs在https://code.google.com/p/unconstrained-melody/downloads/detail?name=UnconstrainedMelody-0.0.0.2-src.zip&can=2&q= – tom 2013-09-13 19:14:49

19

爲了更方便使用,我寫了一個通用的擴展:

public static string ToDescription<TEnum>(this TEnum EnumValue) where TEnum : struct 
{ 
    return Enumerations.GetEnumDescription((Enum)(object)((TEnum)EnumValue)); 
} 

現在我可以這樣寫:

 MyEnum my = MyEnum.HereIsAnother; 
     string description = my.ToDescription(); 
     System.Diagnostics.Debug.Print(description); 

注:代替 「枚舉」 上面有你的類名

50

我把代碼放在一個通用的擴展方法的接受答案中,所以它可以用於各種對象:

public static string DescriptionAttr<T>(this T source) 
{ 
    FieldInfo fi = source.GetType().GetField(source.ToString()); 

    DescriptionAttribute[] attributes = (DescriptionAttribute[])fi.GetCustomAttributes(
     typeof(DescriptionAttribute), false); 

    if (attributes != null && attributes.Length > 0) return attributes[0].Description; 
    else return source.ToString(); 
} 

在原崗位,或其他任何類,它的屬性是裝飾用Description屬性將enum一樣,代碼可以食用這樣的:

string enumDesc = MyEnum.HereIsAnother.DescriptionAttr(); 
string classDesc = myInstance.SomeProperty.DescriptionAttr(); 
+2

string classDesc = myInstance.SomeProperty.DescriptionAttr();這是行不通的!假設你有類Test {public int TestInt {get;設置;}}。因此,如果您將調用新的Test()。TestInt.DescriptionAttr(),您將獲得空引用異常 - 0.GetType()。GetField(「0」) – Vladimirs 2013-12-12 13:34:30