如何将generics枚举转换为int?

我有一个小方法,看起来像这样:

public void SetOptions() where T : Enum { int i = 0; foreach (T obj in Enum.GetValues(typeof(T))) { if (i == 0) DefaultOption = new ListItem(obj.Description(), obj.ToString()); i++; DropDownList.Items.Add(new ListItem(obj.Description(), obj.ToString())); } } 

基本上,我从枚举中填充下拉列表。 Description()实际上是枚举的扩展方法,因此T绝对是enum

但是,我想像对此(int)obj一样对其索引进行任何枚举,但是我得到一个错误,说我无法将T转换为int。 有没有办法做到这一点?

试试这个,

 public void SetOptions() { Type genericType = typeof(T); if (genericType.IsEnum) { foreach (T obj in Enum.GetValues(genericType)) { Enum test = Enum.Parse(typeof(T), obj.ToString()) as Enum; int x = Convert.ToInt32(test); // x is the integer value of enum .......... .......... } } } 

您还可以先将值转换为object ,然后转换为int

C#7.3及以上

使用Enumgenerics约束。

 public static int EnumToInt(this TValue value) where TValue : Enum => (int)(object)value; 

低于C#7.3

没有Enumgenerics约束。

 public static int EnumToInt(this TValue value) where TValue : struct, IConvertible { if(!typeof(TValue).IsEnum) { throw new ArgumentException(nameof(value)); } return (int)(object)value; } 

如果您的枚举inheritance自其他类型,例如从byteinheritance,则InvalidCastException为int将抛出InvalidCastException

您可以检查枚举的基本类型是否为整数。

 public static int EnumToInt(this TValue value) where TValue : Enum { if (!typeof(int).IsAssignableFrom(Enum.GetUnderlyingType(typeof(TValue)))) throw new ArgumentException(nameof(TValue)); return (int)(object)value; } 

或者,如果您使用Convert.ToInt32 ,它将使用int32的IConvertible接口来转换不可用的类型。

 public static int EnumToInt(this TValue value) where TValue : Enum => Convert.ToInt32(value); 

请注意,将uint转换为int和其他后缀会导致意外的行为。 (并装箱到IConvertible并且转换的性能不如仅仅拆箱。)


我建议为每个枚举基类型创建一个方法,以确保返回正确的结果。

这个适用于任何基础类型

 Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())) 

什么时候适用? 例如,当您想要向SqlCommand添加一个值时,它会将枚举转换为0并且您必须明确地将其转换为匹配类型。 但是我们可以写下面的扩展名:

 public static void AddEnum(this SqlParameterCollection parameters, string parameterName, Enum value) { parameters.AddWithValue(parameterName, Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()))); } 

哪个为我们做了一切。

我对你的代码工作感到惊讶。 Enum.GetValues返回一个整数数组 – 这是您要查找的值。 而且,正如其他人所提到的, 你不能将你的generics约束到枚举 。

相反,您应该将Description方法称为常规静态方法而不是扩展方法。

你可以滥用 GetHashCode吗?

 public enum MyEnum { Foo = 100, Bar = 200, Fizz = 0 } static void Main(string[] args) { var i1 = MyEnum.Foo.GetHashCode(); // i1 = 100 var i2 = MyEnum.Bar.GetHashCode(); // i2 = 200 var i3 = MyEnum.Fizz.GetHashCode(); // i3 = 0 } 

请注意:“ GetHashCode() 在设计上只对一件事有用:将对象放在哈希表中。因此名称。” – E. Lippert

派对有点晚了,但是使用Linq这可以优雅地完成:

 public static void SetOptions(this DropDownList dropDownList) { if (!typeof(T).IsEnum) { throw new ArgumentException("Type must be an enum type."); } dropDownList.Items.AddRange(Enum .GetValues(typeof(T)) .Cast() .Select(x => new ListItem(x.ToString(), Convert.ToInt32(x).ToString())) .ToArray()); } 

这是一种更简单的方法。

由于Enum实现了IConvertible,我们可以使用ToInt32(..)。

 int? value = (enumCandidate as IConvertible)?.ToInt32(CultureInfo.InvariantCulture.Numberformat); 

或者,如果您想要通用枚举的通用方法:

 public static int GetEnumValue(T inputEnum) where T: struct, IConvertible { Type t = typeof(T); if (!t.IsEnum) { throw new ArgumentException("Input type must be an enum."); } return inputEnum.ToInt32(CultureInfo.InvariantCulture.NumberFormat); } 

或者更一般:

 public static int GetEnumValue(object enumInput) { Type t = enumInput.GetType(); if (!t.IsEnum) { throw new ArgumentException("Input type must be an enum."); } return ((IConvertible)inputEnum).ToInt32(CultureInfo.InvariantCulture.NumberFormat); } 

扩展Jan关于generics和枚举值的答案:

 void MyFunc(T value) { Type t = typeof(T); if(t.IsEnum) { int valueAsInt = value.GetHashCode(); // returns the integer value } }