Reputation: 22094
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#?
Upvotes: 75
Views: 226967
Reputation: 9936
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.
Upvotes: 114
Reputation: 1613
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
Upvotes: 0
Reputation: 81
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]; } }}
Upvotes: 0
Reputation: 2422
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.
Upvotes: 7
Reputation: 4448
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.
Upvotes: 66
Reputation: 23841
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.
Upvotes: 11
Reputation: 4163
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);
}
}
Upvotes: 1
Reputation: 14781
Use simple casting:
int value = (int) enum.item;
Refer to enum (C# Reference)
Upvotes: 3
Reputation: 20764
Use a cast:
public enum MyEnum : int {
A = 0,
B = 1,
AB = 2,
}
int val = (int)MyEnum.A;
Upvotes: 1