我想创建一个泛型方法,将任何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"));
}
}
有什么建议吗?
答案 0 :(得分:129)
如果你不想演员,
Convert.ToInt32()
可以做到这一点。
直接演员(通过(int)enumValue
)是不可能的。请注意,这也是“危险的”,因为枚举可以有不同的基础类型(int
,long
,byte
...)。
更正式地说:System.Enum
与Int32
没有直接的继承关系(虽然两者都是ValueType
s),因此在类型系统中显式强制转换不正确
答案 1 :(得分:37)
我通过强制转换为对象然后转换为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));
}
答案 2 :(得分:12)
如果您需要将任何枚举转换为其基础类型(并非所有枚举都由int
支持),那么您可以使用:
return System.Convert.ChangeType(
enumValue,
Enum.GetUnderlyingType(enumValue.GetType()));
答案 3 :(得分:11)
为什么需要使用辅助方法重新发明轮子?将enum
值转换为其基础类型是完全合法的。
打字少,而且在我看来更具可读性,使用......
int x = (int)DayOfWeek.Tuesday;
......而不是像......
int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();
答案 4 :(得分:4)
从我的回答here:
给定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();
答案 5 :(得分:1)
从System.Enum
投射到int
对我来说很好(它也在MSDN上)。也许这是一个Resharper bug。
答案 6 :(得分:0)
由于枚举仅限于byte,sbyte,short,ushort,int,uint,long和ulong,我们可以做出一些假设。
我们可以通过使用最大的可用容器来避免转换期间的异常。不幸的是,使用哪个容器并不清楚,因为ulong会因为负数而爆炸,而long会在long.MaxValue和ulong.MaxValue之间爆炸。我们需要根据基础类型在这些选择之间切换。
当然,当结果不适合int时,你仍然需要决定该怎么做。我认为施法是可以的,但仍有一些问题:
这是我的建议,我会留给读者决定在哪里公开这个功能;作为帮助者或延伸者。
public int ToInt(Enum e)
{
unchecked
{
if (e.GetTypeCode() == TypeCode.UInt64)
return (int)Convert.ToUInt64(e);
else
return (int)Convert.ToInt64(e);
}
}
答案 7 :(得分:0)
如果您阅读 Convert.ToInt32
的代码,您可以看到它将 Enum
强制转换为 IConvertible
,然后调用 ToInt32(null)
。
答案 8 :(得分:-1)
不要忘记Enum类型本身有一堆静态辅助函数。如果您只想将枚举的实例转换为相应的整数类型,那么转换可能是最有效的方式。
我认为ReSharper抱怨是因为Enum不是任何特定类型的枚举,枚举本身来自标量值类型,而不是枚举。如果你需要以通用方式进行自适应投射,我会说这可以很好地适应你(请注意,枚举类型本身也包含在通用中:
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);