views:

2921

answers:

5

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?

A: 

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

jpoh
What version of the runtime you using?
JoshBerke
+3  A: 

If you don't want to cast,

Convert.ToInt32()

could do the trick. Your function has the drawback that you won't be able to pass actual enumeration values to it:

Converter.ToInteger(MyEnum.MyEnumConstant); // Will give you an error

since enumerations are value types (and internally represented only by integer constants) while System.Enum is a reference type. So actual enumerations don't "really" derive from Syste.Enum().

By the way, this is also, why your first version is not correct. You cannot cast this base class to an int.

MartinStettner
+3  A: 

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));
    }
BFree
I gave you +1 but this solution is going to work only with C# 3.0 and higher.
Vadim
I think, this only satisfies the compiler. Did you manage to test this at runtime? I could not pass any value to this function...
MartinStettner
Because it's an extension method? Or is something different about enums in older versions of C#?
BFree
I added a test to the end of my post. I tried that and it worked for me.
BFree
@BFree: It seems only to work with extension methods. I tried it with an "old-style" function (in C# 2.0) and didn't manage to find the syntax to actually pass any value to it (that's what my previous comment was about)
MartinStettner
A: 

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);
jrista
Unfortunately, in your example E can be any type. Generics don't allow me to use Enum as type parameter constraint.I cannot say:where T : Enum
Vadim
You could use where T: struct, though. Its not quite as strict as you want it to be, but it would cut out any reference type (which I think is what your trying to do.)
jrista
you can use:if (!typeof(E).IsEnum) throw new ArgumentException("E must be an enumerated type");
diadiora
+1  A: 

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();
LukeH
I want to convert ANY enum value. Ie, I have a variety of classes that have enum fields that are being processed by some code in a generic way. This is why a simple cast to int is not appropriate.
orj
@orj, I'm not really sure what you mean. Can you give an example showing the usage you need?
LukeH
Sometimes you can't directly cast an enum, such as in the case of a generic method. Because generic methods can't be constrained to enums, you have constrain it to something like struct, which can't be cast into an int. In that case, you can use Convert.ToInt32(enum) to do it.
Daniel T.