使用泛型将枚举转换为字典

时间:2013-02-23 11:20:20

标签: c# linq generics

我试图创建一个我可以调用的方法,它将从枚举中返回一个类型为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);
    }
}

即将到来的补充错误

  

运营商'&lt;'不能应用于'方法组'和'System.Type'

类型的操作数

任何人都可以看到我的错误在哪里吗?

3 个答案:

答案 0 :(得分:6)

GetEnumDictionary方法中有两个主要错误:

首先,Cast<typeof(T)>没有意义。它只是Cast<T>

然后,你不能简单地将类型T的值转换为int和int,但是你必须先将它转换为object 所以,你应该像这样改变你的方法:

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

但问题是你可以传递你想要的任何类型的T,甚至是非枚举类型。 不幸的是,您不能将泛型类型限制为Enum,因此您需要在运行时检查它:

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 :(得分:4)

错误在于:

.Cast<typeof(T)>()

您正在尝试使用Type类的实例作为通用参数,您应该使用该类型:

.Cast<T>()

答案 2 :(得分: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)
  • 禁止将T投放到int,因此您需要使用enumIConvertible
  • 这一事实

这是一个快速demo on ideone