【问题标题】:Convert generic T into System.Enum将泛型 T 转换为 System.Enum
【发布时间】:2014-11-24 09:03:08
【问题描述】:

我有一个Enums 列表作为IEnumerable<T>,我需要循环每个项目并得到它的描述,如下所示:

IEnumerable<T> values = (T[])Enum.GetValues(typeof(T));
foreach (Enum value in values)
{
    String mylist = Common.MyExtensions.getEnumDescription(value);
}

...

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();
}

这会在 foreach 部分产生错误

无法将“T”转换为 System.Enum。

IEnumerable 不是 System.Enum 的列表吗? 什么样的演员可以做到这一点?

【问题讨论】:

  • 枚举不应该是 T 吗?
  • 也许尝试不进行投射。像这样: var values = Enum.GetValues(typeof(T));
  • 枚举变量在哪里?用它代替 T。
  • 从 Enum.GetValues 返回的集合不是枚举的集合,而是整数的集合(很可能)。

标签: c# enums


【解决方案1】:

进行演员表的一种方法是:

Enum enumValueError = (Enum)value;
//compiler error: Cannot convert type 'xxx' to 'System.Enum'
Enum enumValueNoError = value as Enum; 
//no error, but enumValueNoError will be null if value is not an Enum

【讨论】:

【解决方案2】:

IEnumerable 不是 System.Enum 的列表吗?什么样的演员可以做到这一点?

是的,但编译器无法确定这一点。 T 在运行时可以是任何东西。在这种情况下,您通常使用泛型类型约束,但 where T : Enum 无效,因此您可以做的是:

  1. 不要让你的方法通用,如果你只想使用枚举,请将参数类型更改为Enum
  2. 使用where T : struct 约束至少确保T 是一个值类型,并检查该类型是否在您的方法内部是Enum,如果它没有抛出异常等(不推荐这样做)李>

【讨论】:

  • 对于您的第一个解决方案:它需要更多工作:Enum.GetValues(t) 其中t 是运行时Type 实例,不能转换为Enum[]。对于您的第二个解决方案:这并没有告诉 OP 如何消除关于 TEnum 之间转换的编译时错误。
【解决方案3】:

我猜你正在寻找这样的东西(稍微改变了实现):

public enum Test
{
    [Description("This")]
    A,
    B,
    C,
    D
}

private IEnumerable<string> GetEnumDescription<T>()
{
    var type = typeof(T);

    if (!type.IsEnum) throw new ArgumentException("Only Enum types allowed");

    foreach (var value in Enum.GetValues(type).Cast<Enum>())
    {
        yield return getEnumDescription(value);
    }
}

public 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 desc = GetEnumDescription<Test>(); // "This", "B", "C", "D"

【讨论】:

    【解决方案4】:

    考虑使用您已经在使用的类型 T...

    IEnumerable<T> values = (T[])Enum.GetValues(typeof(T));
    foreach (T value in values)
    {
        String mylist = Common.MyExtensions.getEnumDescription(value);
    }
    

    您还必须使 getEnumDescription 成为通用的。

    【讨论】:

    • 那么在不同的地方也会出现同样的错误:getEnumDescription(value);
    【解决方案5】:
    foreach(var e in values)
    {
        if(e is Enum)
        {
            Enum eAsEnum = (Enum)e;
            String mylist = Common.MyExtensions.getEnumDescription(eAsEnum);
        }
    }
    

    【讨论】:

    • 这仍然会在演员Enum eAsEnum = (Enum)e; 中给出相同的错误
    猜你喜欢
    • 1970-01-01
    • 2017-03-31
    • 2010-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-11
    • 1970-01-01
    相关资源
    最近更新 更多