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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/908543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 02:34:45  来源:igfitidea点击:

How to convert from System.Enum to base integer?

c#enumstype-conversion

提问by orj

I'd like to create a generic method for converting any System.Enum derived type to its corresponding integer value, without casting and preferably without parsing a string.

我想创建一个通用方法,用于将任何 System.Enum 派生类型转换为其相应的整数值,而不进行强制转换,最好不解析字符串。

Eg, what I want is something like this:

例如,我想要的是这样的:

// Trivial example, not actually what I'm doing.
class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        (int)anEnum;
    }
}

But this doesn't appear to work. Resharper reports that you can not cast expression of type 'System.Enum' to type 'int'.

但这似乎不起作用。Resharper 报告说您不能将“System.Enum”类型的表达式转换为“int”类型。

Now I've come up with this solution but I'd rather have something more efficient.

现在我想出了这个解决方案,但我宁愿有一些更有效的方法。

class Converter
{
    int ToInteger(System.Enum anEnum)
    {
        return int.Parse(anEnum.ToString("d"));
    }
}

Any suggestions?

有什么建议?

采纳答案by MartinStettner

If you don't want to cast,

如果你不想投,

Convert.ToInt32()

could do the trick.

可以做到这一点。

The direct cast (via (int)enumValue) is not possible. Note that this would also be "dangerous" since an enum can have different underlying types (int, long, byte...).

直接转换 (via (int)enumValue) 是不可能的。请注意,这也将是“危险的”,因为枚举可以具有不同的基础类型(int, long, byte...)。

More formally: System.Enumhas no direct inheritance relationship with Int32(though both are ValueTypes), so the explicit cast cannot be correct within the type system

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

回答by jpoh

Casting from a System.Enumto an intworks fine for me (it's also on the MSDN). Perhaps it's a Resharper bug.

从 aSystem.Enum到 an 的转换int对我来说很好(它也在MSDN 上)。也许这是一个 Resharper 错误。

回答by BFree

I got it to work by casting to an object and then to an int:

我通过转换到一个对象然后转换到一个 int 来让它工作:

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return (int)((object)enumValue);
    }
}

This is ugly and probably not the best way. I'll keep messing with it, to see if I can come up with something better....

这很丑陋,可能不是最好的方法。我会继续弄乱它,看看我是否能想出更好的东西......

EDIT: Was just about to post that Convert.ToInt32(enumValue) works as well, and noticed that MartinStettner beat me to it.

编辑:刚要发布 Convert.ToInt32(enumValue) 也可以工作,并注意到 MartinStettner 击败了我。

public static class EnumExtensions
{
    public static int ToInt(this Enum enumValue)
    {
        return Convert.ToInt32(enumValue);
    }
}

Test:

测试:

int x = DayOfWeek.Friday.ToInt();
Console.WriteLine(x); // results in 5 which is int value of Friday

EDIT 2: In the comments, someone said that this only works in C# 3.0. I just tested this in VS2005 like this and it worked:

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

回答by jrista

Don't forget that the Enum type itself has a bunch of static helper functions in it. If all you want to do is convert an instance of the enum to its corresponding integer type, then casting is probably the most efficient way.

不要忘记 Enum 类型本身有一堆静态辅助函数。如果您只想将枚举的实例转换为其相应的整数类型,那么强制转换可能是最有效的方法。

I think ReSharper is complaining because Enum isn't an enumeration of any particular type, and enumerations themselves derive from a scalar valuetype, not Enum. If you need adaptable casting in a generic way, I would say this could suite you well (note that the enumeration type itself is also included in the generic:

我认为 ReSharper 是在抱怨,因为 Enum 不是任何特定类型的枚举,并且枚举本身源自标量值类型,而不是 Enum。如果您需要以通用方式进行适应性转换,我会说这很适合您(请注意,枚举类型本身也包含在通用中:

public static EnumHelpers
{
    public static T Convert<T, E>(E enumValue)
    {
        return (T)enumValue;
    }
}

This could then be used like so:

然后可以这样使用:

public enum StopLight: int
{
    Red = 1,
    Yellow = 2,
    Green = 3
}

// ...

int myStoplightColor = EnumHelpers.Convert<int, StopLight>(StopLight.Red);

I can't say for sure off the top of my head, but the above code might even be supported by C#'s type inference, allowing the following:

我不能肯定地说我的头顶,但上面的代码甚至可能被 C# 的类型推断支持,允许以下内容:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);

回答by LukeH

Why do you need to reinvent the wheel with a helper method? It's perfectly legal to cast an enumvalue to its underlying type.

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

It's less typing, and in my opinion more readable, to use...

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

int x = (int)DayOfWeek.Tuesday;

...rather than something like...

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

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

回答by nawfal

From my answer here:

从我这里的回答:

Given eas in:

给出e如下:

Enum e = Question.Role;

Then these work:

然后这些工作:

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

The last two are plain ugly. The first one should be more readable, though the second one is much faster. Or may be an extension method is the best, best of both worlds.

最后两个简直丑死了。第一个应该更具可读性,尽管第二个要快得多。或者可能是一种扩展方法是最好的,两全其美。

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

Now you can call:

现在你可以调用:

e.GetValue<int>(); //or
e.GetIntValue();

回答by Drew Noakes

If you need to convert anyenum to its underlying type (not all enums are backed by int) then you can use:

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

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

回答by eisenpony

Since Enums are restricted to byte, sbyte, short, ushort, int, uint, long and ulong, we can make some assumptions.

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

We can avoid exceptions during conversion by using the largest available container. Unfortunately, which container to use is not clear because ulong will blow up for negative numbers and long will blow up for numbers between long.MaxValue and ulong.MaxValue. We need to switch between these choices based on the underlying type.

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

Of course, you still need to decide what to do when the result doesn't fit inside an int. I think casting is okay, but there are still some gotchas:

当然,当结果不适合 int 时,您仍然需要决定该怎么做。我认为铸造没问题,但仍有一些问题:

  1. for enums based on a type with a field space larger than int (long and ulong), it's possible some enums will evaluate to the same value.
  2. casting a number larger than int.MaxValue will throw an exception if you are in a checked region.
  1. 对于基于字段空间大于 int(long 和 ulong)的类型的枚举,某些枚举可能会评估为相同的值。
  2. 如果您在检查区域中,投射一个大于 int.MaxValue 的数字将引发异常。

Here's my suggestion, I'll leave it to the reader to decide where to expose this function; as a helper or an extension.

这是我的建议,我会留给读者来决定在哪里公开这个函数;作为帮手或扩展。

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