views:

2183

answers:

5

say I have the following declarations:

public enum Complexity { Low = 0, Normal = 1, Medium = 2,  High = 3 }
public enum Priority { Normal = 1, Medium = 2,  High = 3, Urgent = 4 }

and I want to code it so that I could get the enum value (not the index, like I earlier mentioned):

//should store the value of the Complexity enum member Normal, which is 1
int complexityValueToStore = EnumHelper.GetEnumMemberValue(Complexity.Normal); 
//should store the value 4
int priorityValueToStore = EnumHelper.GetEnumMemberValue(Priority.Urgent);

How should this reusable function look like?

tia! -ren

+7  A: 

You can find the integer value of an enum by casting:

int complexityValueToStore = (int)Complexity.Normal;
Smashery
+12  A: 

Revised answer (after question clarification)

No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.

Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.

Original answer

What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:

public static int GetEnumMemberIndex<T>(T element)
    where T : struct
{
    T[] values = (T[]) Enum.GetValues(typeof(T));
    return Array.IndexOf(values, element);
}
Jon Skeet
i mean the numeric value. I know I can cast to int, but I was hoping I could code it cleaner
You're right. It was a silly idea. I got carried away while building an EnumHelper class.
A: 

If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.

If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.

However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.

Reed Copsey
+2  A: 

I realize this isn't what you asked, but it's something you might appreciate.

I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:

public enum Complexity { Low = 0, Normal = 1, Medium = 2,  High = 3 }

int valueOfHigh = Complexity.High - Complexity.Low;

This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:

public enum Priority { Normal = 1, Medium = 2,  High = 3, Urgent = 4 }

int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;

I find this technique much more aesthetically appealing than casting to int.

I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.

Mark Maxham
+1 thats the point!!
Perpetualcoder
This also supposes that the enum values are contiguous (is that the word?), and start at a known value, and are in the right order. Try `enum DealBreaker { First=3, Second=1, Third=19 }`. Oh, and that the enum doesn't have the [Flags] attribute.
Benjol
A: 

The most generic way I know of is to read the value__ field using reflection. This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.

public static object GetValue(Enum e)
{
    return e.GetType().GetField("value__").GetValue(e);
}

Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3));                //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8));        //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64

Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.

Nathan Baulch