How to convert from System.Enum to base integer?

C#EnumsType Conversion

C# Problem Overview


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?

C# Solutions


Solution 1 - C#

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

Solution 2 - C#

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

Solution 3 - C#

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

Solution 4 - C#

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

Solution 5 - C#

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

Solution 6 - C#

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

Solution 7 - C#

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

Solution 8 - C#

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

Solution 9 - C#

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionorjView Question on Stackoverflow
Solution 1 - C#MartinStettnerView Answer on Stackoverflow
Solution 2 - C#BFreeView Answer on Stackoverflow
Solution 3 - C#Drew NoakesView Answer on Stackoverflow
Solution 4 - C#LukeHView Answer on Stackoverflow
Solution 5 - C#nawfalView Answer on Stackoverflow
Solution 6 - C#jpohView Answer on Stackoverflow
Solution 7 - C#eisenponyView Answer on Stackoverflow
Solution 8 - C#DweditView Answer on Stackoverflow
Solution 9 - C#jristaView Answer on Stackoverflow