2013-02-23 96 views
0

即時嘗試創建一個方法,我可以調用哪個將返回一個從Enum類型Dictionary<int,string>字典。使用泛型來鑄造一個枚舉到字典

我想使用泛型。

這是到目前爲止我的代碼...

public class Enums 
{ 
    public static Dictionary<int, string> GetEnumDictionary<T>() 
    { 
     return Enum.GetValues(typeof(T))) 
      .Cast<typeof(T)>() 
      .ToDictionary(t => (int)t, t => t.ToString()); 
    } 

    /// <summary> 
    /// Fuel Type Enum 
    /// </summary> 
    public enum FuelTypes 
    { 
     Petrol = 1, 
     Diesel = 2, 
     Hybrid = 3, 
     Electric = 4 
    } 
} 

單元測試...

[TestClass] 
public class EnumTests 
{ 
    [TestMethod] 
    public void TestGetEnumDictionary() 
    { 
     Dictionary<int, string> dict = new Dictionary<int, string>(); 
     dict = Enums.GetEnumDictionary<Enums.FuelTypes>(); 
     Assert.IsTrue(dict != null); 
    } 
} 

的compliation錯誤即時得到是

操作 '<' 不能應用於「方法組」和「System.Type」類型的操作數

任何人都可以看到我的錯誤在哪裏?

+0

它看起來像你沒有發佈你的實際代碼。錯誤消息是關於'GetEnumDictionary(Type)'方法,您沒有發佈。 – svick 2013-02-23 11:22:51

+0

即在頂部 - >公共靜態字典 GetEnumDictionary () – JGilmartin 2013-02-23 11:23:29

+0

這是一種不同的方法。該錯誤消息討論類似'public static Dictionary GetEnumDictionary(Type type)'或類似的東西。 – svick 2013-02-23 11:24:24

回答

6

你有兩個主要的GetEnumDictionary方法中的錯誤:

首先,Cast<typeof(T)>沒有意義。這只是Cast<T>。然後,你不能簡單地將類型T的值轉換爲int,但是你必須先將它轉換爲對象。
所以,你應該改變你的方法是這樣的:

public static Dictionary<int, string> GetEnumDictionary<T>() 
{ 
    return Enum.GetValues(typeof(T)) 
     .Cast<T>() 
     .ToDictionary(t => (int)(object)t, t => t.ToString()); 
} 

但問題是,你可以通過你要到T無論何種類型,甚至非枚舉類型。 不幸的是你不能約束泛型類型是一個枚舉,所以你需要在運行時檢查:

public static Dictionary<int, string> GetEnumDictionary<T>() 
{ 
    if(!typeof(T).IsEnum) 
     throw new ArgumentException("T is not an Enum type"); 
    return Enum.GetValues(typeof(T)) 
     .Cast<T>() 
     .ToDictionary(t => (int)(object)t, t => t.ToString()); 
} 

編輯:

由於正確地指出的svick,基礎類型的枚舉可以與int不同。 因此,例如,它不會與這樣的枚舉工作:

enum MyEnum : long 
{ 
    Foo, 
    Bar, 
} 

更安全,或許你也應該檢查在運行時:

public static Dictionary<int, string> GetEnumDictionary<T>() 
{ 
    if (!typeof(T).IsEnum) 
     throw new ArgumentException("T is not an Enum type"); 
    if (Enum.GetUnderlyingType(typeof(T)) != typeof(int)) 
     throw new ArgumentException("The underlying type of the enum T is not Int32"); 
    return Enum.GetValues(typeof(T)) 
     .Cast<T>() 
     .ToDictionary(t => (int)(object)t, t => t.ToString()); 
} 

最後要注意的。

您可以更改代碼以支持具有積分值的枚舉,該積分值適合Int32。事實上,您可以簡單地將Convert.ToInt32()代替直接投射到int,或者如其他答案中正確顯示的那樣,您可以利用IConvertible接口。
但是,在我看來,它並沒有給你帶來很多好處。由於這種方法並不安全,因此您應該在知道自己在做什麼時使用它;因此,如果你想要一本字典出「長枚舉」(例如),只需使用/再拍方法...

+1

注意這一點,它只適用於具有「int」底層類型的枚舉(雖然幾乎所有的枚舉都可以)。 – svick 2013-02-23 11:37:01

+0

是的,你是對的忘了它。我會在答案中提到它;) – digEmAll 2013-02-23 11:38:04

4

的錯誤是在這裏:

.Cast<typeof(T)>() 

您正在嘗試使用Type類的實例作爲通用參數,你應該使用,而不是類型:

.Cast<T>() 
+0

優秀,請注意我也改變了 - > .ToDictionary(t => Convert.ToInt32(t),t => t.ToString()); – JGilmartin 2013-02-23 11:35:04

3

這裏是你如何能做到這:

public static IDictionary<int, string> GetEnumDictionary<T>() 
where T : IConvertible 
{ 
    return Enum 
     .GetValues(typeof(T)) 
     .Cast<T>() 
     .ToDictionary(
      t => t.ToInt32(CultureInfo.InvariantCulture) 
     , t => t.ToString() 
     ); 
} 

有在你的代碼的幾個小問題:

  • Cast應該是T,不typeof(T)
  • 鑄造Tint是禁止的,所以你需要使用的事實,enum s爲IConvertible

這裏是一個快速demo on ideone