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

发布于 2024-07-22 11:54:37 字数 526 浏览 6 评论 0原文

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

有什么建议么?

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.

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'.

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

秋凉 2024-07-29 11:54:37

如果你不想施放,

Convert.ToInt32()

也可以这样做。

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

更正式地说:System.EnumInt32 没有直接继承关系(尽管两者都是 ValueType),因此显式转换在以下范围内无法正确类型系统

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

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

暮光沉寂 2024-07-29 11:54: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));
    }

I got it to work by casting to an object and then to an 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.

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:

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));
    }
泪痕残 2024-07-29 11:54:37

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

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

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

return System.Convert.ChangeType(
    enumValue,
    Enum.GetUnderlyingType(enumValue.GetType()));
猫烠⑼条掵仅有一顆心 2024-07-29 11:54:37

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

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

int x = (int)DayOfWeek.Tuesday;

...而不是类似...

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

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

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();
塔塔猫 2024-07-29 11:54:37

从我的回答这里

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

From my answer here:

Given e as in:

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();
绮筵 2024-07-29 11:54:37

System.Enum 转换为 int 对我来说效果很好(它也在 MSDN)。 也许这是 Resharper 的错误。

Casting from a System.Enum to an int works fine for me (it's also on the MSDN). Perhaps it's a Resharper bug.

[旋木] 2024-07-29 11:54:37

由于枚举仅限于 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);
  }
}

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

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.

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:

  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.

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);
  }
}
夏见 2024-07-29 11:54:37

如果您阅读 Convert.ToInt32 的代码,您可以看到它将 Enum 转换为 IConvertible,然后调用 ToInt32(null )

If you read the code for Convert.ToInt32, you can see that it casts the Enum to IConvertible, then calls ToInt32(null).

云柯 2024-07-29 11:54:37

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

我认为 ReSharper 正在抱怨,因为 Enum 不是任何特定类型的枚举,并且枚举本身派生自标量值类型,而不是 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);

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.

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:

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:

int myStoplightColor = EnumHelpers.Convert<int>(StopLight.Red);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文