如何从 System.Enum 转换为基本整数?
-
05-09-2019 - |
题
我想创建一个通用方法,用于将任何 System.Enum 派生类型转换为其相应的整数值,无需进行强制转换,最好无需解析字符串。
例如,我想要的是这样的:
// Trivial example, not actually what I'm doing.
class Converter
{
int ToInteger(System.Enum anEnum)
{
(int)anEnum;
}
}
但这似乎不起作用。Resharper 报告您无法将“System.Enum”类型的表达式转换为“int”类型。
现在我已经提出了这个解决方案,但我宁愿有更有效的方法。
class Converter
{
int ToInteger(System.Enum anEnum)
{
return int.Parse(anEnum.ToString("d"));
}
}
有什么建议么?
解决方案
如果你不想投,
Convert.ToInt32()
可以胜任。
在直接铸造(经由(int)enumValue
)是不可能的。注意,这也将是“危险的”,因为一个枚举可以有不同的基础类型(int
,long
,byte
...)。
更正式:System.Enum
具有Int32
没有直接继承关系(虽然两者都是ValueType
s),所以显式转换不能类型系统内正确
其他提示
我得到它通过浇铸到一个对象,然后为int工作:
public static class EnumExtensions
{
public static int ToInt(this Enum enumValue)
{
return (int)((object)enumValue);
}
}
这是丑陋的,可能不是最好的方式。我会继续用它搞乱,看看我能想出更好的东西......
编辑:正要张贴Convert.ToInt32(enumValue)的作品,以及,发现MartinStettner打我给它
public static class EnumExtensions
{
public static int ToInt(this Enum enumValue)
{
return Convert.ToInt32(enumValue);
}
}
测试:
int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday
编辑2:在评论,有人说,这仅适用于C#3.0。我只是测试这在VS2005这样,它的工作:
public static class Helpers
{
public static int ToInt(Enum enumValue)
{
return Convert.ToInt32(enumValue);
}
}
static void Main(string[] args)
{
Console.WriteLine(Helpers.ToInt(DayOfWeek.Friday));
}
如果您需要转换的任何的枚举的基础类型(不是所有枚举被int
支持),那么你可以使用:
return System.Convert.ChangeType(
enumValue,
Enum.GetUnderlyingType(enumValue.GetType()));
为什么你需要使用一个辅助方法推倒重来?它是完全合法的一个enum
值转换为它的基本类型。
这是少打字,在我看来更具有可读性,使用...
int x = (int)DayOfWeek.Tuesday;
...而不是像...
int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();
这是我的答案这里:
鉴于e
如:
Enum e = Question.Role;
然后,这些工作:
int i = Convert.ToInt32(e);
int i = (int)(object)e;
int i = (int)Enum.Parse(e.GetType(), e.ToString());
int i = (int)Enum.ToObject(e.GetType(), e);
最后两个是难看。第一个应该是更具可读性,但第二个是要快得多。或者可以是一个扩展方法是最好的,两全其美。
public static int GetIntValue(this Enum e)
{
return e.GetValue<int>();
}
public static T GetValue<T>(this Enum e) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
{
return (T)(object)e;
}
现在您可以拨打:
e.GetValue<int>(); //or
e.GetIntValue();
从System.Enum
铸造到int
为我工作正常(这也是对的 MSDN )。也许这是一个ReSharper的错误。
由于枚举仅限于 byte、sbyte、short、ushort、int、uint、long 和 ulong,因此我们可以做出一些假设。
我们可以通过使用最大的可用容器来避免转换过程中的异常。不幸的是,使用哪个容器并不清楚,因为 ulong 会因负数而爆炸,而 long 会因 long.MaxValue 和 ulong.MaxValue 之间的数字而爆炸。我们需要根据底层类型在这些选择之间进行切换。
当然,您仍然需要决定当结果不适合 int 时该怎么做。我觉得选角还可以,但是还是有一些问题:
- 对于基于字段空间大于 int(long 和 ulong)的类型的枚举,某些枚举可能会计算出相同的值。
- 如果您位于检查区域中,则转换大于 int.MaxValue 的数字将引发异常。
这是我的建议,我将让读者决定在哪里公开这个函数;作为帮助者或扩展。
public int ToInt(Enum e)
{
unchecked
{
if (e.GetTypeCode() == TypeCode.UInt64)
return (int)Convert.ToUInt64(e);
else
return (int)Convert.ToInt64(e);
}
}
不要忘记,枚举类型本身有一堆在它静态辅助功能。如果你想要做的是枚举的实例转换到其相应的整数类型,然后浇铸可能是最有效的方式。
我认为ReSharper的抱怨因为枚举不是任何特定类型的枚举和枚举本身从一个标量值类型,而不是枚举派生。如果你需要适应铸造在一个通用的方法,我会说这可能适合你很好(注意,枚举类型本身也包括在通用:
public static EnumHelpers
{
public static T Convert<T, E>(E enumValue)
{
return (T)enumValue;
}
}
这然后可以使用像这样:
public enum StopLight: int
{
Red = 1,
Yellow = 2,
Green = 3
}
// ...
int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);
我不能肯定地说了我的头顶部,但上面的代码可能甚至是C#的类型推断的支持,允许以下内容:
int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);