将通用 T 转换为 System.Enum

本文关键字:System Enum 转换 | 更新日期: 2023-09-27 18:31:36

我有一个Enum的列表作为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"转换为系统枚举。

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

将通用 T 转换为 System.Enum

进行强制转换的一种方法是:

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

IEnumerable不是系统枚举的列表吗?什么样的演员可以做到这一点?

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

  1. 不要使方法通用,如果只想使用枚举,请将参数类型更改为Enum
  2. 使用where T : struct约束至少确保T是值类型,并检查该类型是否Enum在方法内部,是否未引发异常等(不建议这样做)

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

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"

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

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

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

foreach(var e in values)
{
    if(e is Enum)
    {
        Enum eAsEnum = (Enum)e;
        String mylist = Common.MyExtensions.getEnumDescription(eAsEnum);
    }
}