2013-06-18 43 views
1

我想为给定泛型Enum类型生成底层值和名称的列表。我想要原生的基础值(如object s)。获取泛型Enum的底层值

public static ReadOnlyCollection<EnumerationMember> ListFromEnum<TEnum>() 
    { 
     Type enumType = typeof(TEnum); 
     if (!enumType.IsEnum) 
     { 
      throw new InvalidOperationException("TEnum is not an enum"); 
     } 

     Type underlyingType = Enum.GetUnderlyingType(enumType); 
     TEnum[] enumValues = (TEnum[])Enum.GetValues(enumType); 

     return enumValues 
      .Select(ev => new EnumerationMember(
       (???)ev, 
       EnumerationExtension.GetDescription(enumType, ev))) 
      .ToList() 
      .AsReadOnly(); 
    } 

    public class EnumerationMember 
    { 
     public EnumerationMember(object value, string description) 
     { 
      this.Value = value; 
      this.Description = description; 
     } 

     public object Value { get; private set; } 

     public string Description { get; private set; } 
    } 

回答

6

在最简单的:

.Select(ev => Convert.ChangeType(ev, underlyingType)) 

但我更倾向于将返回一个正确类型的阵列 - 你甚至都不需要转换的步骤,那么:

public static Array ListValuesFromEnum<T>() 
{ 
    Type enumType = typeof(T); 
    Type underlyingType = Enum.GetUnderlyingType(enumType); 
    Array enumValues = Enum.GetValues(enumType); 

    var arr = Array.CreateInstance(underlyingType, enumValues.Length); 
    enumValues.CopyTo(arr, 0); 
    return arr; 
} 
+0

我认为,但我不知道它是否会运行它通过常规转换函数或只是内部将其转换为underlyingType。有什么方法可以使用Type来显式执行演员,还是这样? – Monstieur

+1

@Kurian好吧,我检查了一下,它似乎有效 - 盒装值被输入为“short”(等),而不是“SomeEnum”。顺便说一句,我个人会尝试返回一个'short []'(通过'Array'作为方法的返回类型),但这只是我;这个代码并没有太大的区别。 –

+0

@Kurian ooh,发现如果使用右类型的数组方法,内置的保留值转换会自动处理它 - 请参阅编辑 –

0

这里是你的一些工作代码,它使用Convert.ChangeType

public static ReadOnlyCollection<EnumerationMember> ListValuesFromEnum<T>() 
{ 
    Type enumType = typeof(T); 
    Type underlyingType = Enum.GetUnderlyingType(enumType); 
    T[] enumValues = (T[])Enum.GetValues(enumType); 

    return enumValues 
     .Select(ev => new EnumerationMember(Convert.ChangeType(ev,underlyingType), ev.ToString())) 
     .ToList() 
     .AsReadOnly(); 
}   

这里是一个现场演示:http://rextester.com/EHOE12097

+0

这适用于我更新的问题,但我感兴趣的是比Convert.ChangeType更高效的方法。 – Monstieur

+0

more *高效*方法?这种方法有什么特别低效的吗? – Jamiec

+0

我不确定它是简单地在内部执行演员还是通过某种转换功能运行它。 – Monstieur