如何从System.Enum转换为基本整数?

问题描述 投票:87回答:8

我想创建一个泛型方法,用于将任何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"));
    }
}

有什么建议?

c# enums type-conversion
8个回答
126
投票

如果你不想演员,

Convert.ToInt32()

可以做到这一点。

直接演员(通过(int)enumValue)是不可能的。请注意,这也是“危险的”,因为枚举可以有不同的基础类型(intlongbyte ......)。

更正式地说:System.EnumInt32没有直接的继承关系(虽然两者都是ValueTypes),所以显式转换在类型系统中是不正确的


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));
    }

12
投票

如果您需要将任何枚举转换为其基础类型(并非所有枚举都由int支持),那么您可以使用:

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));

11
投票

为什么需要使用辅助方法重新发明轮子?将enum值转换为其基础类型是完全合法的。

它打字较少,而且在我看来更具可读性,使用...

int x = (int)DayOfWeek.Tuesday;

......而不是......

int y = Converter.ToInteger(DayOfWeek.Tuesday);
// or
int z = DayOfWeek.Tuesday.ToInteger();

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();

1
投票

System.Enumint的投射对我来说很好(它也在MSDN上)。也许这是一个Resharper错误。


0
投票

由于枚举仅限于byte,sbyte,short,ushort,int,uint,long和ulong,因此我们可以做出一些假设。

我们可以通过使用最大的可用容器来避免转换期间的异常。不幸的是,使用哪个容器并不清楚,因为ulong会因为负数而爆炸,而long会在long.MaxValue和ulong.MaxValue之间爆炸。我们需要根据基础类型在这些选择之间切换。

当然,当结果不适合int时,你仍然需要决定做什么。我认为施法是可以的,但仍有一些问题:

  1. 对于基于字段空间大于int(long和ulong)的类型的枚举,某些枚举可能会评估为相同的值。
  2. 如果您处于选中区域,则转换大于int.MaxValue的数字将引发异常。

这是我的建议,我会留给读者决定在哪里公开这个功能;作为帮助者或延伸者。

public int ToInt(Enum e)
{
  unchecked
  {
    if (e.GetTypeCode() == TypeCode.UInt64)
      return (int)Convert.ToUInt64(e);
    else
      return (int)Convert.ToInt64(e);
  }
}

-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);
© www.soinside.com 2019 - 2024. All rights reserved.