jim
jim

Reputation: 27426

Get int value from enum in C#

I have a class called Questions (plural). In this class there is an enum called Question (singular) which looks like this.

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

In the Questions class I have a get(int foo) function that returns a Questions object for that foo. Is there an easy way to get the integer value off the enum so I can do something like this Questions.Get(Question.Role)?

Upvotes: 2393

Views: 2443370

Answers (29)

Ahmed Adel Shaker
Ahmed Adel Shaker

Reputation: 59

I'm following this approach to access the value of Enums

public class Enum<TEnum> where TEnum : Enum
     {
    
         public static string[] ToArray()
         {
             return Enum.GetValues(typeof(TEnum))
                .Cast<TEnum>()
                .ToList()
                .Select(c => c.ToString())
                .ToArray();
         }
         public static List<EnumValues> ToList()
         {
             return Enum.GetValues(typeof(TEnum))
               .Cast<TEnum>()
               .ToList()
               .Select(c => new EnumValues((int)(object)c, c.ToString()))
               .ToList();
    
         }
     }
     public class EnumValues
     {
         public int key { get; set; }
         public string value { get; set; } = string.Empty;
    
         public EnumValues(int _key, string _value)
         {
             key = _key;
             value = _value;
         }
     }
    
   

and to use this method call

Enum<MyEnum>.ToList()

or, you can return the enum value as int by

(int)MyEnum.Value;

Upvotes: -1

David L
David L

Reputation: 33863

Nearly all of the current answers use Convert or cast to object before the target type, which results in boxing and unboxing operations. This causes heap allocations and may not be acceptable for hot paths.

Since the majority of these answers were written, System.Runtime.CompilerServices.Unsafe was introduced, enabling low-level manipulation of pointers.

In combination with generics, the Unsafe class allows us to change the underlying type of the System.Enum parameter safely, with zero allocations, and with performance that is nearly indistinguishable from an empty method duration:

public long GetEnumValue<T>(T enumInstance) where T : unmanaged, Enum
{
    var size = Unsafe.SizeOf<T>();
    
    if (size == Unsafe.SizeOf<byte>())
    {
        return Unsafe.As<T, byte>(ref enumInstance);
    }
    else if (size == Unsafe.SizeOf<short>())
    {
        return Unsafe.As<T, short>(ref enumInstance);
    }
    else if (size == Unsafe.SizeOf<int>())
    {
        return Unsafe.As<T, int>(ref enumInstance); 
    }
    else if (size == Unsafe.SizeOf<long>())
    {
        return Unsafe.As<T, long>(ref enumInstance);
    }
    
    return -1; // or throw if you prefer
}

Convert vs Unsafe benchmark


If it is preferable to always return an int, you can do so, although if the backing field of the enum exceeds int.MaxValue, it will overflow:

public int GetEnumValue<T>(T enumInstance) where T : unmanaged, Enum
{
    var size = Unsafe.SizeOf<T>();
    
    if (size == Unsafe.SizeOf<byte>())
    {
        return Unsafe.As<T, byte>(ref enumInstance);
    }
    else if (size == Unsafe.SizeOf<short>())
    {
        return Unsafe.As<T, short>(ref enumInstance);
    }
    else if (size == Unsafe.SizeOf<int>())
    {
        return Unsafe.As<T, int>(ref enumInstance); 
    }
    else if (size == Unsafe.SizeOf<long>())
    {
        return Unsafe.As<T, int>(ref enumInstance);
    }
    
    return -1; // or throw if you prefer
}

If the following were used:

public enum EnumLong : long
{
    First,
    Second,
    Third = (long)(int.MaxValue) + 1
}

var val = GetEnumValue(EnumLong.Third);

-2147483648 would be returned due to an overflow. It is extremely unlikely that developers would create enums with such large flag values, but is always a possibility.

Upvotes: 0

IggyBar
IggyBar

Reputation: 138

will give you the a list with all the integer values of the enum :

List enumValues = Enum.GetValues(typeof(EnumClass)).Cast().ToList();

Upvotes: -1

sooraj
sooraj

Reputation:

Example:

public enum EmpNo
{
    Raj = 1,
    Rahul,
    Priyanka
}

And in the code behind to get the enum value:

int setempNo = (int)EmpNo.Raj; // This will give setempNo = 1

or

int setempNo = (int)EmpNo.Rahul; // This will give setempNo = 2

Enums will increment by 1, and you can set the start value. If you don't set the start value it will be assigned as 0 initially.

Upvotes: 68

S M Abrar Jahin
S M Abrar Jahin

Reputation: 14588

You should have used Type Casting as we can use in any other language.

If your enum is like this-

public enum Question
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

And you need to cast to an int, then do this-

Question q = Question.Role;
.............
.............
int something = (int) q;

Re-

In C#, there are two types of casting:

  • Implicit Casting (automatically) - converting a smaller type to a larger type size like-

char -> int -> long -> float -> double

  • Explicit Casting (manually) - converting a larger type to a smaller size type like-

double -> float -> long -> int -> char

More can be found in here.

Upvotes: 5

GinCanhViet
GinCanhViet

Reputation: 469

Use:

Question question = Question.Role;
int value = question.GetHashCode();

It will result in value == 2.

This is only true if the enum fits inside an int.

Upvotes: 17

Jeff
Jeff

Reputation: 654

I came up with this extension method that includes current language features. By using dynamic, I don't need to make this a generic method and specify the type which keeps the invocation simpler and consistent:

public static class EnumEx
{
    public static dynamic Value(this Enum e)
    {
        switch (e.GetTypeCode())
        {
            case TypeCode.Byte:
            {
                return (byte) (IConvertible) e;
            }

            case TypeCode.Int16:
            {
                return (short) (IConvertible) e;
            }

            case TypeCode.Int32:
            {
                return (int) (IConvertible) e;
            }

            case TypeCode.Int64:
            {
                return (long) (IConvertible) e;
            }

            case TypeCode.UInt16:
            {
                return (ushort) (IConvertible) e;
            }

            case TypeCode.UInt32:
            {
                return (uint) (IConvertible) e;
            }

            case TypeCode.UInt64:
            {
                return (ulong) (IConvertible) e;
            }

            case TypeCode.SByte:
            {
                return (sbyte) (IConvertible) e;
            }
        }

        return 0;
    }

Upvotes: -2

Gauravsa
Gauravsa

Reputation: 6528

public enum Suit : int
{
    Spades = 0,
    Hearts = 1,
    Clubs = 2,
    Diamonds = 3
}

Console.WriteLine((int)(Suit)Enum.Parse(typeof(Suit), "Clubs"));

// From int
Console.WriteLine((Suit)1);

// From a number you can also
Console.WriteLine((Suit)Enum.ToObject(typeof(Suit), 1));

if (typeof(Suit).IsEnumDefined("Spades"))
{
    var res = (int)(Suit)Enum.Parse(typeof(Suit), "Spades");
    Console.Out.WriteLine("{0}", res);
}

Upvotes: 11

VPP
VPP

Reputation: 789

In Visual Basic, it should be:

Public Enum Question
    Role = 2
    ProjectFunding = 3
    TotalEmployee = 4
    NumberOfServers = 5
    TopBusinessConcern = 6
End Enum

Private value As Integer = CInt(Question.Role)

Upvotes: -1

Erik Karlsson
Erik Karlsson

Reputation: 608

My favourite hack with int or smaller enums:

GetHashCode();

For an enum

public enum Test
{
    Min = Int32.MinValue,
    One = 1,
    Max = Int32.MaxValue,
}

This,

var values = Enum.GetValues(typeof(Test));

foreach (var val in values)
{
    Console.WriteLine(val.GetHashCode());
    Console.WriteLine(((int)val));
    Console.WriteLine(val);
}

outputs

one
1
1
max
2147483647
2147483647
min
-2147483648
-2147483648

Disclaimer:

It doesn't work for enums based on long.

Upvotes: 5

Doug
Doug

Reputation: 215

Maybe I missed it, but has anyone tried a simple generic extension method?

This works great for me. You can avoid the type cast in your API this way but ultimately it results in a change type operation. This is a good case for programming Roslyn to have the compiler make a GetValue<T> method for you.

    public static void Main()
    {
        int test = MyCSharpWrapperMethod(TestEnum.Test1);

        Debug.Assert(test == 1);
    }

    public static int MyCSharpWrapperMethod(TestEnum customFlag)
    {
        return MyCPlusPlusMethod(customFlag.GetValue<int>());
    }

    public static int MyCPlusPlusMethod(int customFlag)
    {
        // Pretend you made a PInvoke or COM+ call to C++ method that require an integer
        return customFlag;
    }

    public enum TestEnum
    {
        Test1 = 1,
        Test2 = 2,
        Test3 = 3
    }
}

public static class EnumExtensions
{
    public static T GetValue<T>(this Enum enumeration)
    {
        T result = default(T);

        try
        {
            result = (T)Convert.ChangeType(enumeration, typeof(T));
        }
        catch (Exception ex)
        {
            Debug.Assert(false);
            Debug.WriteLine(ex);
        }

        return result;
    }
}

Upvotes: 14

plavozont
plavozont

Reputation: 813

One more way to do it:

Console.WriteLine("Name: {0}, Value: {0:D}", Question.Role);

It will result in:

Name: Role, Value: 2

Upvotes: 18

SixOThree
SixOThree

Reputation: 771

Use an extension method instead:

public static class ExtensionMethods
{
    public static int IntValue(this Enum argEnum)
    {
        return Convert.ToInt32(argEnum);
    }
}

And the usage is slightly prettier:

var intValue = Question.Role.IntValue();

Upvotes: 22

Grx70
Grx70

Reputation: 10349

The easiest solution I can think of is overloading the Get(int) method like this:

[modifiers] Questions Get(Question q)
{
    return Get((int)q);
}

where [modifiers] can generally be same as for the Get(int) method. If you can't edit the Questions class or for some reason don't want to, you can overload the method by writing an extension:

public static class Extensions
{
    public static Questions Get(this Questions qs, Question q)
    {
        return qs.Get((int)q);
    }
}

Upvotes: 5

Bronek
Bronek

Reputation: 11245

You can do this by implementing an extension method to your defined enum type:

public static class MyExtensions
{
    public static int getNumberValue(this Question questionThis)
    {
        return (int)questionThis;
    }
}

This simplifies getting the int value of the current enum value:

Question question = Question.Role;
int value = question.getNumberValue();

or

int value = Question.Role.getNumberValue();

Upvotes: 12

Mathijs Van Der Slagt
Mathijs Van Der Slagt

Reputation: 241

If you want to get an integer for the enum value that is stored in a variable, for which the type would be Question, to use for example in a method, you can simply do this I wrote in this example:

enum Talen
{
    Engels = 1, Italiaans = 2, Portugees = 3, Nederlands = 4, Duits = 5, Dens = 6
}

Talen Geselecteerd;    

public void Form1()
{
    InitializeComponent()
    Geselecteerd = Talen.Nederlands;
}

// You can use the Enum type as a parameter, so any enumeration from any enumerator can be used as parameter
void VeranderenTitel(Enum e)
{
    this.Text = Convert.ToInt32(e).ToString();
}

This will change the window title to 4, because the variable Geselecteerd is Talen.Nederlands. If I change it to Talen.Portugees and call the method again, the text will change to 3.

Upvotes: 23

Nathon
Nathon

Reputation: 171

To ensure an enum value exists and then parse it, you can also do the following.

// Fake Day of Week
string strDOWFake = "SuperDay";

// Real Day of Week
string strDOWReal = "Friday";

// Will hold which ever is the real DOW.
DayOfWeek enmDOW;

// See if fake DOW is defined in the DayOfWeek enumeration.
if (Enum.IsDefined(typeof(DayOfWeek), strDOWFake))
{
    // This will never be reached since "SuperDay"
    // doesn't exist in the DayOfWeek enumeration.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWFake);
}
// See if real DOW is defined in the DayOfWeek enumeration.
else if (Enum.IsDefined(typeof(DayOfWeek), strDOWReal))
{
    // This will parse the string into it's corresponding DOW enum object.
    enmDOW = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), strDOWReal);
}

// Can now use the DOW enum object.
Console.Write("Today is " + enmDOW.ToString() + ".");

Upvotes: 16

Michael Petrotta
Michael Petrotta

Reputation: 60952

It's easier than you think - an enum is already an int. It just needs to be reminded:

int y = (int)Question.Role;
Console.WriteLine(y); // Prints 2

Upvotes: 49

Jeffrey Ferreiras
Jeffrey Ferreiras

Reputation: 271

Since enums can be declared with multiple primitive types, a generic extension method to cast any enum type can be useful.

enum Box
{
    HEIGHT,
    WIDTH,
    DEPTH
}

public static void UseEnum()
{
    int height = Box.HEIGHT.GetEnumValue<int>();
    int width = Box.WIDTH.GetEnumValue<int>();
    int depth = Box.DEPTH.GetEnumValue<int>();
}

public static T GetEnumValue<T>(this object e) => (T)e;

Upvotes: 6

Kamran Shahid
Kamran Shahid

Reputation: 4124

Following is the extension method

public static string ToEnumString<TEnum>(this int enumValue)
{
    var enumString = enumValue.ToString();
    if (Enum.IsDefined(typeof(TEnum), enumValue))
    {
        enumString = ((TEnum) Enum.ToObject(typeof (TEnum), enumValue)).ToString();
    }
    return enumString;
}

Upvotes: 3

JohnLBevan
JohnLBevan

Reputation: 24470

I have recently converted away from using enums in my code in favour of instead using classes with protected constructors and predefined static instances (thanks to Roelof - C# Ensure Valid Enum Values - Futureproof Method).

In light of that, below's how I'd now approach this issue (including implicit conversion to/from int).

public class Question
{
    // Attributes
    protected int index;
    protected string name;
    // Go with a dictionary to enforce unique index
    //protected static readonly ICollection<Question> values = new Collection<Question>();
    protected static readonly IDictionary<int,Question> values = new Dictionary<int,Question>();

    // Define the "enum" values
    public static readonly Question Role = new Question(2,"Role");
    public static readonly Question ProjectFunding = new Question(3, "Project Funding");
    public static readonly Question TotalEmployee = new Question(4, "Total Employee");
    public static readonly Question NumberOfServers = new Question(5, "Number of Servers");
    public static readonly Question TopBusinessConcern = new Question(6, "Top Business Concern");

    // Constructors
    protected Question(int index, string name)
    {
        this.index = index;
        this.name = name;
        values.Add(index, this);
    }

    // Easy int conversion
    public static implicit operator int(Question question) =>
        question.index; //nb: if question is null this will return a null pointer exception

    public static implicit operator Question(int index) =>        
        values.TryGetValue(index, out var question) ? question : null;

    // Easy string conversion (also update ToString for the same effect)
    public override string ToString() =>
        this.name;

    public static implicit operator string(Question question) =>
        question?.ToString();

    public static implicit operator Question(string name) =>
        name == null ? null : values.Values.FirstOrDefault(item => name.Equals(item.name, StringComparison.CurrentCultureIgnoreCase));


    // If you specifically want a Get(int x) function (though not required given the implicit converstion)
    public Question Get(int foo) =>
        foo; //(implicit conversion will take care of the conversion for you)
}

The advantage of this approach is you get everything you would have from the enum, but your code's now much more flexible, so should you need to perform different actions based on the value of Question, you can put logic into Question itself (i.e. in the preferred OO fashion) as opposed to putting lots of case statements throughout your code to tackle each scenario.


NB: Answer updated 2018-04-27 to make use of C# 6 features; i.e. declaration expressions and lambda expression body definitions. See revision history for original code. This has the benefit of making the definition a little less verbose; which had been one of the main complaints about this answer's approach.

Upvotes: 34

WonderWorker
WonderWorker

Reputation: 9072

public enum QuestionType
{
    Role = 2,
    ProjectFunding = 3,
    TotalEmployee = 4,
    NumberOfServers = 5,
    TopBusinessConcern = 6
}

...is a fine declaration.

You do have to cast the result to int like so:

int Question = (int)QuestionType.Role

Otherwise, the type is still QuestionType.

This level of strictness is the C# way.

One alternative is to use a class declaration instead:

public class QuestionType
{
    public static int Role = 2,
    public static int ProjectFunding = 3,
    public static int TotalEmployee = 4,
    public static int NumberOfServers = 5,
    public static int TopBusinessConcern = 6
}

It's less elegant to declare, but you don't need to cast it in code:

int Question = QuestionType.Role

Alternatively, you may feel more comfortable with Visual Basic, which caters for this type of expectation in many areas.

Upvotes: 15

PablosBicicleta
PablosBicicleta

Reputation: 2501

Declare it as a static class having public constants:

public static class Question
{
    public const int Role = 2;
    public const int ProjectFunding = 3;
    public const int TotalEmployee = 4;
    public const int NumberOfServers = 5;
    public const int TopBusinessConcern = 6;
}

And then you can reference it as Question.Role, and it always evaluates to an int or whatever you define it as.

Upvotes: 229

Tetraneutron
Tetraneutron

Reputation: 33861

Just cast the enum, e.g.

int something = (int) Question.Role;

The above will work for the vast majority of enums you see in the wild, as the default underlying type for an enum is int.

However, as cecilphillip points out, enums can have different underlying types. If an enum is declared as a uint, long, or ulong, it should be cast to the type of the enum; e.g. for

enum StarsInMilkyWay:long {Sun = 1, V645Centauri = 2 .. Wolf424B = 2147483649};

you should use

long something = (long)StarsInMilkyWay.Wolf424B;

Upvotes: 3011

cecilphillip
cecilphillip

Reputation: 11596

Since Enums can be any integral type (byte, int, short, etc.), a more robust way to get the underlying integral value of the enum would be to make use of the GetTypeCode method in conjunction with the Convert class:

enum Sides {
    Left, Right, Top, Bottom
}
Sides side = Sides.Bottom;

object val = Convert.ChangeType(side, side.GetTypeCode());
Console.WriteLine(val);

This should work regardless of the underlying integral type.

Upvotes: 386

JaimeArmenta
JaimeArmenta

Reputation: 139

int number = Question.Role.GetHashCode();

number should have the value 2.

Upvotes: 13

nawfal
nawfal

Reputation: 73253

On a related note, if you want to get the int value from System.Enum, then given e here:

Enum e = Question.Role;

You can use:

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. I prefer the first one.

Upvotes: 130

Nalan Madheswaran
Nalan Madheswaran

Reputation: 10572

Try this one instead of convert enum to int:

public static class ReturnType
{
    public static readonly int Success = 1;
    public static readonly int Duplicate = 2;
    public static readonly int Error = -1;        
}

Upvotes: 3

jerryjvl
jerryjvl

Reputation: 20151

Question question = Question.Role;
int value = (int) question;

Will result in value == 2.

Upvotes: 113

Related Questions