2013-05-16 138 views
4

我有下面的代碼。我需要它的名稱和在指定枚舉類型的每個枚舉值的價值創造KeyValuePair<string, string>List無法鑄造枚舉到INT

public static List<KeyValuePair<string, string>> GetEnumList<TEnum>() where TEnum : struct 
{ 
    if (!typeof(TEnum).IsEnum) 
     throw new ArgumentException("Type must be an enumeration"); 
    List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); 
    foreach (TEnum e in Enum.GetValues(typeof(TEnum))) 
     list.Add(new KeyValuePair<string, string>(e.ToString(), ((int)e).ToString())); 
    return list; 
} 

但是,表達式((int)e).ToString()生成以下錯誤。

Cannot convert type 'TEnum' to 'int'

我只是想將一個枚舉實例轉換爲一個整數。誰能告訴我爲什麼這不起作用?

編輯:

我想這個版本:

enum Fruit : short 
{ 
    Apple, 
    Banana, 
    Orange, 
    Pear, 
    Plum, 
} 

void Main() 
{ 
    foreach (var x in EnumHelper.GetEnumList<Fruit>()) 
     Console.WriteLine("{0}={1}", x.Value, x.Key); 
} 

public static List<KeyValuePair<string, string>> GetEnumList<TEnum>() where TEnum : struct 
{ 
    if (!typeof(TEnum).IsEnum) 
     throw new ArgumentException("Type must be an enumeration"); 
    List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); 
    foreach (TEnum e in Enum.GetValues(typeof(TEnum))) 
    { 
     list.Add(new KeyValuePair<string, string>(e.ToString(), ((int)(dynamic)e).ToString())); 
    } 
    return list; 
} 

但是,這給我的錯誤:

Cannot convert type 'System.Enum' to 'int'

+0

你的'TEnum'永遠不會是'int',因爲'TEnum:struct'所以它總是一個結構 – WiiMaxx

+0

@WiiMaxx:'struct'只是表示它是一個值類型,'int'是。 –

+0

,但你如何從[this](http://msdn.microsoft.com/en-au/library/ah19swz4(v = vs.80).aspx)獲得'int',因爲我將結構理解爲一個簡單容器的值 – WiiMaxx

回答

9

TEnum是 - 每個約束 - 一個結構。它不保證是一個枚舉。

但是,因爲你強制執行這個約束在運行時,你可以利用的事實,每個枚舉實現IConvertible

foreach (IConvertible e in Enum.GetValues(typeof(TEnum))) 
{ 
    list.Add(new KeyValuePair<string, string>(
     e.ToString(), 
     e.ToType(
      Enum.GetUnderlyingType(typeof(TEnum)), 
      CultureInfo.CurrentCulture).ToString())); 
} 

所有存在缺陷的其它方法有:

你可以先轉換爲然後到int

請注意,這將在運行時,如果基礎類型的枚舉比int以外的任何失敗。

這可以通過鑄造dynamic鑄造int之前必須克服:

((int)(dynamic)e).ToString() 

然而,這又存在一些問題:

如果枚舉是long類型,ulonguint它會返回不正確的值。您可以通過鑄造ulong而不是int減少的問題,但仍然會負枚舉值返回無效值。

+1

值得注意的是,對''''Enum'和'int'的轉換仍然是一個盒子+ unbox,但。當然,如果他們要'ToString()',這可能並不重要; p –

+0

@MarcGravell:沒錯。順便說一句:演員必須是「對象」而不是「枚舉」 - 糾正了答案。 –

+0

@JonathanWood:請參閱更新。 –

3

的唯一安全的方式做到這一點,沒有nowing基本類型,就是用它創建的方法! Enum類中的方法。即使你可以嘗試使用IConvertable接口。

// Get underlying type, like int, ulong, etc. 
Type underlyingType = Enum.GetUnderlyingType(typeof(T); 
// Convert the enum to that type. 
object underlyingValue = e.ToType(underlyingType, null); 
// Convert that value to string. 
string s = underlyingValue.ToString(); 

或簡稱:

public static List<KeyValuePair<string, string>> GetEnumList<TEnum>() 
      where TEnum : struct, IConvertible 
{ 
    if (!typeof(TEnum).IsEnum) 
     throw new ArgumentException("Type must be an enumeration"); 
    List<KeyValuePair<string, string>> list = new List<KeyValuePair<string, string>>(); 
    foreach (TEnum e in Enum.GetValues(typeof(TEnum))) 
    { 
     list.Add(new KeyValuePair<string, string> 
     (
      e.ToString(), 
      e.ToType(Enum.GetUnderlyingType(typeof(TEnum)), null).ToString() 
     )); 
    } 
    return list; 
} 

如果你不想使用IConvertable,嘗試使用Convert類:

string s = e.ToType(Enum.GetUnderlyingType(typeof(T)), null).ToString(); 

你可以在你像這樣的代碼實現它:

string s = Convert.ChangeType(e, Enum.GetUnderlyingType(typeof(TEnum))).ToString(); 
+0

'Enum.ToObject'是相反的方法。它將數值轉換爲枚舉成員。執行你的代碼 - 修復編譯器錯誤後 - 產生一個'ArgumentException':*提供的類型必須是Enum.Parameter名稱:enumType *。 –

+0

這一切都沒有爲我編譯。 –

+0

@丹尼爾:該死的,你是對的......矯正來了! –