0

我试图创建一个我可以调用的方法,它将 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);
    }
}

我得到的编译错误是

运算符“<”不能应用于“方法组”和“System.Type”类型的操作数

谁能看到我的错误在哪里?

4

3 回答 3

7

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,甚至是非枚举类型。不幸的是,您不能将泛型类型约束为 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. 实际上,您可以简单地放置 aConvert.ToInt32()而不是使用直接转换,int或者,如其他答案中正确显示的那样,您可以利用该IConvertible接口。
但是,在我看来,它并没有给你带来很多好处。由于此方法不是真正的类型安全,因此您应该在知道自己在做什么时使用它;因此,如果您想要一个“长枚举”中的字典(例如),只需使用/制作另一种方法......

于 2013-02-23T11:35:03.610 回答
4

错误在这里:

.Cast<typeof(T)>()

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

.Cast<T>()
于 2013-02-23T11:33:16.180 回答
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,因此您需要使用enums 是IConvertible

这是关于 ideone 的快速演示

于 2013-02-23T11:37:28.843 回答