74

In C, enums, internally equates to an integer. Therefore we can treat data types of enum as integer also.

How to achieve the same with C#?

Shamim Hafiz - MSFT
  • 21,454
  • 43
  • 116
  • 176

9 Answers9

112

Firstly, there could be two values that you're referring to:

Underlying Value

If you are asking about the underlying value, which could be any of these types: byte, sbyte, short, ushort, int, uint, long or ulong

Then you can simply cast it to it's underlying type. Assuming it's an int, you can do it like this:

int eValue = (int)enumValue;

However, also be aware of each items default value (first item is 0, second is 1 and so on) and the fact that each item could have been assigned a new value, which may not necessarily be in any order particular order! (Credit to @JohnStock for the poke to clarify).

This example assigns each a new value, and show the value returned:

public enum MyEnum
{
    MyValue1 = 34,
    MyValue2 = 27
}

(int)MyEnum.MyValue2 == 27; // True

Index Value

The above is generally the most commonly required value, and is what your question detail suggests you need, however each value also has an index value (which you refer to in the title). If you require this then please see other answers below for details.

Iain Ward
  • 9,850
  • 5
  • 34
  • 41
  • 1
    The int value isn't necessarily the index as shown in user1027167's answer below. On second thought, I don't think it's clear if OP actually want the index or the int value... – Svend Hansen Sep 05 '19 at 14:41
  • This answer is wrong and makes huge assumptions about your enum in order for it to work. – John Stock Oct 09 '20 at 20:36
  • @JohnStock Sorry in what way is it wrong? Can you please elaborate? Bear in mind that it was written almost 10 years ago, and was written in response to someone who seemingly wanted a simple answer to a simple question, so yes assumptions were made and obviously it can, as always, be more complicated but it appears to have satisfied what they were seeking! – Iain Ward Oct 10 '20 at 22:51
  • OP is asking for an index. Your answer assumes that an enumeration has a consistent set of consecutive incrementing values like 1,2,3,4,5, which of course is very often not true with enumerations. It could be in a reverse order, not consecutive, seemingly random values or even not numeric at all. You should delete your answer because it only works for a very specific use case and will cause errors in other cases. If you read the other responses on this page, this error in your solution (and other people) has been pointed out numerous times. Nothing has changed in 10 years – John Stock Oct 12 '20 at 15:44
  • @JohnStock Ahh I see! Right OK, I understand what you're saying but to be honest it comes down to your interpretation if what he's asking. Although he states 'Index' in the title (and I'll admit I missed that) his actual question about enums equating to an integer suggests, and I believe in the majority of situations, refers to the underlying value of the enum, and not specifically the index value itself. I can't think of a situation where I've ever need the index value myself! (Is there one??) so yes, I made an assumption there and still believe it was the right decision as he accepted it. – Iain Ward Oct 13 '20 at 20:03
  • @JohnStock However, I disagree with your statement about assuming that the underlying values are in consecutive order, hence why I specifically assigned each one an integer value different to their default value to avoid any confusion there. So yes, I agree that it requires further clarification to avoid any confusion about an index value, and will update my answer to point to other answers as that's not something I can take credit for, but that to me and everyone else that's up-voted my answer, is definitely an edge case and not the most common use, hence it;s still a valid and correct answer – Iain Ward Oct 13 '20 at 20:09
  • @JohnStock And I'm not sure about you, but plenty has changed for me in the past 10 years!! It was in reference to my experience, skills and understanding back then. I was basically fresh out of university and was very much a newbie!! – Iain Ward Oct 13 '20 at 20:13
  • This also works after getting an enum via `Reflection` casting to `int` will still provide the correct value, The names and values are cached –  Apr 29 '23 at 20:07
65

Another way to convert an Enum-Type to an int:

enum E
{
    A = 1,   /* index 0 */
    B = 2,   /* index 1 */
    C = 4,   /* index 2 */
    D = 4    /* index 3, duplicate use of 4 */
}

void Main()
{
    E e = E.C;
    int index = Array.IndexOf(Enum.GetValues(e.GetType()), e);
    // index is 2

    E f = (E)(Enum.GetValues(e.GetType())).GetValue(index);
    // f is  E.C
}

More complex but independent from the INT values assigned to the enum values.

user1027167
  • 4,320
  • 6
  • 33
  • 40
  • 4
    This is a better answer than the accepted one (or the many other similar answers) since they all seem to assume that your enum values are assigned with sequential numeric values and often that is not the case. – Christopher King Dec 06 '17 at 00:46
  • Monster!!!! Nice answer. Worked perfectly in a method with generalization of Enum Type! Thanks – Peter R Dec 02 '19 at 12:11
  • 2
    Careful when using flags, the index is calculated by the numerically sorted value of the flag, and not the order in which they are defined. In above example, if instead you define A=1,C=4, B=2 then B still has an index of 1, even though it was defined after C. This can cause unexpected results when using composite flags. Again in above example if we add a new flag "AB = A | B' then its value will be 3, and the index of C will change from 2 in the above example to 3 as "AB' is slotted in between B and C in index order. – JimbobTheSailor Sep 15 '20 at 05:10
11

By default the underlying type of each element in the enum is integer.

enum Values
{
   A,
   B,
   C
}

You can also specify custom value for each item:

enum Values
{
   A = 10,
   B = 11,
   C = 12
}
int x = (int)Values.A; // x will be 10;

Note: By default, the first enumerator has the value 0.

Homam
  • 23,263
  • 32
  • 111
  • 187
7

You can directly cast it:

enum MyMonthEnum { January = 1, February, March, April, May, June, July, August, September, October, November, December };

public static string GetMyMonthName(int MonthIndex)
{
  MyMonthEnum MonthName = (MyMonthEnum)MonthIndex;
  return MonthName.ToString();
}

For Example:

string MySelectedMonthName=GetMyMonthName(8);
 //then MySelectedMonthName value will be August.
Durgesh Pandey
  • 2,314
  • 4
  • 29
  • 43
3

Use simple casting:

int value = (int) enum.item;

Refer to enum (C# Reference)

Akram Shahda
  • 14,655
  • 4
  • 45
  • 65
  • This isn't what the title asks for, this has, strictly speaking, nothing to do with the index of the enum entry. – Kresten Jul 15 '23 at 16:04
1

Use a cast:

public enum MyEnum : int    {
    A = 0,
    B = 1,
    AB = 2,
}


int val = (int)MyEnum.A;
thumbmunkeys
  • 20,606
  • 8
  • 62
  • 110
1
using System;
public class EnumTest 
{
    enum Days {Sat=1, Sun, Mon, Tue, Wed, Thu, Fri};

    static void Main() 
    {

        int x = (int)Days.Sun;
        int y = (int)Days.Fri;
        Console.WriteLine("Sun = {0}", x);
        Console.WriteLine("Fri = {0}", y);
    }
}
Aravind
  • 4,125
  • 1
  • 28
  • 39
0

One reason that the designers c# might have chosen to NOT have enums auto convert was to prevent accidentally mixing different enum types...

e.g. this is bad code followed by a good version
enum ParkingLevel { GroundLevel, FirstFloor};
enum ParkingFacing { North, East, South, West }
void Test()
{
    var parking = ParkingFacing.North; // NOT A LEVEL
    // WHOOPS at least warning in editor/compile on calls
    WhichLevel(parking); 

    // BAD  wrong type of index, no warning
    var info = ParkinglevelArray[ (int)parking ];
}


// however you can write this, looks complicated 
// but avoids using casts every time AND stops miss-use
void Test()
{
  ParkingLevelManager levels = new ParkingLevelManager();
  // assign info to each level
  var parking = ParkingFacing.North;

  // Next line wrong mixing type 
  // but great you get warning in editor or at compile time      
  var info=levels[parking];

  // and.... no cast needed for correct use
  var pl = ParkingLevel.GroundLevel;
  var infoCorrect=levels[pl];

}
class ParkingLevelInfo { /*...*/ }
class ParkingLevelManager
{
    List<ParkingLevelInfo> m_list;
    public ParkingLevelInfo this[ParkingLevel x] 
 { get{ return m_list[(int)x]; } }}
PJJ
  • 61
  • 5
0

In answering this question I define 'value' as the value of the enum item, and index as is positional location in the Enum definition (which is sorted by value). The OP's question asks for 'index' and various answer have interpreted this as either 'index' or 'value' (by my definitions). Sometimes the index is equal to numerical value.

No answer has specifically addressed the case of finding the index (not value) where the Enum is an Enum flag.

Enum Flag
{
    none = 0       // not a flag, thus index =-1
    A = 1 << 0,   // index should be 0
    B = 1 << 1,   // index should be 1 
    C = 1 << 2,   // index should be 2 
    D = 1 << 3,   // index should be 3,
    AandB = A | B // index is composite, thus index = -1 indicating undefined
    All = -1      //index is composite, thus index = -1 indicating undefined
}

In the case of Flag Enums, the index is simply given by

var index = (int)(Math.Log2((int)flag)); //Shows the maths, but is inefficient

However, the above solution is (a) Inefficient as pointed out by @phuclv (Math.Log2() is floating point and costly) and (b) Does not address the Flag.none case, nor any composite flags - flags that are composed of other flags (eg the 'AandB' flag as in my example).

DotNetCore If using dot net core we can address both a) and b) above as follows:

int setbits = BitOperations.PopCount((uint)flag); //get number of set bits
if (setbits != 1) //Finds ECalFlags.none, and all composite flags
    return -1;   //undefined index
int index = BitOperations.TrailingZeroCount((uint)flag); //Efficient bit operation

Not DotNetCore The BitOperations only work in dot net core. See @phuclv answer here for some efficient suggestions https://stackoverflow.com/a/63582586/6630192

  • @user1027167 answer will not work if composite flags are used, as per my comment on his answer
  • Thankyou to @phuclv for suggestions on improving efficiency
JimbobTheSailor
  • 1,441
  • 1
  • 12
  • 21
  • `Math.Log2` is very slow, `BitOperations.TrailingZeroCount` will be much faster. And you don't need `Convert.ToInt32` to get an int, a simple cast is enough [How to get numeric position of an enum in its definition list?](https://stackoverflow.com/a/63582586/995714) – phuclv Sep 15 '20 at 06:33
  • this assumes a particular definition of "index" (although note that in the actual question, when OP says "index" they actually mean "value"); a valid argument could be made that the "index" should refer to enum values *that are defined*, therefore since `None=0` is *defined* first, it would have index 0 - but that then gets into *further* complications because the order of reflection APIs is not itself defined! My point: there are a lot of definitional things in this answer that are implicitly assumed to be axiomatic, but which are more subtle than that – Marc Gravell Sep 15 '20 at 09:08
  • @Marc Gravell agree there is ambiguity between 'index' and 'value'. Therefore we define 'value' as the value of the enum item, and index as is positional location in the enum definition (which is sorted by value). There are many other questions that look at the value, but I came here specifically looking for index-the positional location.. A number of other answers have implicitly defined index similarly, and as separate to value (see @user1027167). Regarding None=0, in a Flags Enum it could not be considered an index, as it can not be used as a Flag..It is a good point you make though. – JimbobTheSailor Sep 15 '20 at 10:03
  • "and index as is positional location in the enum definition (which is sorted by value)" - those are conflicting statements; the enum definition does not have to be sorted by value (and the values do not need to be distinct), and it is not *possible* to deduce the definition order at runtime, because the reflection API explicitly does not define/guarantee order – Marc Gravell Sep 15 '20 at 10:11
  • @MarcGravell. Hi Marc, focusing only on Enum Flags, while the values may not need to be distinct, we always define them as distinct as that is necessary for the the flags to be distinct. Given that, the index of or distinct flags *are* sorted by the numerical value of the flag. For example let flags be A=1 <<0, B=1<<1, C= 1<<2 as defined in that numerical order. We expect the indexes to be A=0, B=1. C=2 Now if we add a composite flag AandB = A|B, then we should expect the indexes to be the same., but by value order they become A=0,B=1, C=3, as A|B slips in between them. My answer avoids this – JimbobTheSailor Sep 15 '20 at 10:33