55

I have a simple Enum

 public enum TestEnum
 {
     TestOne = 3,
     TestTwo = 4
 }

var testing = TestEnum.TestOne;

And I want to retrieve its value (3) via reflection. Any ideas on how to do this?

Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
mat-mcloughlin
  • 6,492
  • 12
  • 45
  • 62
  • To your comments: In a context where you in any sense 'have' the value `TestEnum.TestOne`, you *already have* the value `3`. What do you actually have? – AakashM Aug 25 '10 at 12:01
  • i see to many answers here point out the (int)TestEnum. a person would not ask for the way to do it with reflection if it aint necessary. Dependent injection maybe or why i came here Compatibility for a standard library to have a framework only feature. if there. – Courtney The coder Aug 22 '18 at 18:36

16 Answers16

72

Great question Mat.

The scenario of the question is this:

You have some unknown enum type and some unknown value of that type and you want to get the underlying numeric value of that unknown value.

This is the one-line way of doing this using reflection:

object underlyingValue = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()));

If value happens to be TestEnum.TestTwo, then value.GetType() would be equal to typeof(TestEnum), Enum.GetUnderlyingType(value.GetType()) would be equal to typeof(int) and value would be 3 (boxed; see http://msdn.microsoft.com/en-us/library/yz2be5wk.aspx for more details about boxing and unboxing values).

Why would one ever need to write such code? In my case, I have a routine that copies values from a viewmodel to a model. I use this in all my handlers in an ASP.NET MVC project as part of a very clean and elegant architecture for writing handlers that do not have the security problems the handlers generated by the Microsoft templates do.

The model is generated by the Entity Framework from the database and it contains a field of type int. The viewmodel has a field of some enum type, let's call it RecordStatus, which I have defined elsewhere in my project. I decided to support enums fully in my framework. But now there is a mismatch between the type of the field in the model and the type of the corresponding field in the viewmodel. My code detects this and converts the enum to an int using the code similar to the one-liner given above.

Miltos Kokkonidis
  • 3,888
  • 20
  • 14
  • 6
    Your answer is a good answer to the question you were asking yourself, but I don't think it's an answer to the question asked here. –  Nov 14 '12 at 11:48
  • 7
    Thanks for the comment, but actually this *is* the answer to the question Mat was asking. – Miltos Kokkonidis Nov 16 '12 at 08:40
  • 5
    More specifically, Mat asked how he can get the (underlying) value (3) of an enum value (testing) of some simple enum type(TestEnum) *using reflection*. Daniel and Fredrik assumed he was asking the wrong thing and replied that reflection is unnecessary and Pranay answered a different question altogether (how to list the values of an enum type using reflection). It was exactly because the currently upvoted answers do not address the question asked that I rephrased it, answered it, and gave an example of a situation where one might want to do exactly what Mat was asking about! :-) – Miltos Kokkonidis Nov 16 '12 at 09:03
  • I agree that the other questions don't really answer the question as asked either. Pranay's accepted answer can be correct if the question is asked wrong (as I suspect it is), if the goal isn't to convert `TestEnum.TestOne` to 3, but to convert `"TestOne"` (a string) to 3. Your answer does convert `TestEnum.TestOne` to 3, but does not do so via reflection (you do use reflection, but not in the conversion). Thinking about it, though, that's just a plain silly requirement in the question, and you're right to ignore it. –  Nov 16 '12 at 09:33
  • 2
    @hvd: Thanks for your comment. I 'd say that the very fact that the second argument passed to Convert.ChangeType is a type object (i.e. an object of type System.Type which is a subclass of System.Reflection.MemberInfo) means that even the conversion itself *is* using the reflection infrastructure of the .NET CLR! So, I don't think I have ignored the requirement in Mat's question nor that he was wrong to add it in the first place! Without this requirement, it would seem like Mat was after the kind of answer Fredrik and Daniel gave. – Miltos Kokkonidis Nov 16 '12 at 11:07
  • 3
    I answered the question as it stood without trying to second-guess or doubt Mat's ability to express what he wanted. If, as you say, he wanted to be able to go from "TestEnum.TestOne" to 3 rather than from TestEnum.TestOne to 3 using reflection, then I would agree that his question does not convey that. But as it stands, it is a perfectly reasonable question and now it has an answer. :-) @mjmcloug: Any comments? – Miltos Kokkonidis Nov 16 '12 at 11:11
  • 1
    @MiltosKokkonidis Very elegant solution, helped me too :) – G.Y May 01 '13 at 05:52
  • 1
    @MiltosKokkonidis I agree with the way you interpreted this question. Thanks for the solution. – Skrymsli May 24 '13 at 17:14
  • This one really deserves more +1 – mrmillsy Oct 23 '13 at 12:51
  • After 2 miserable hours, I finally found this solution. Thanks a lot! :-) – zdarsky.peter May 20 '17 at 23:45
44

You can use the System.Enum helpers:

System.Type enumType = typeof(TestEnum);
System.Type enumUnderlyingType = System.Enum.GetUnderlyingType(enumType);
System.Array enumValues = System.Enum.GetValues(enumType);

for (int i=0; i < enumValues.Length; i++)
{
    // Retrieve the value of the ith enum item.
    object value = enumValues.GetValue(i);

    // Convert the value to its underlying type (int, byte, long, ...)
    object underlyingValue = System.Convert.ChangeType(value, enumUnderlyingType);

    System.Console.WriteLine(underlyingValue);
}

Outputs

3
4

OLP
  • 803
  • 8
  • 10
  • 7
    This is the better answer. Because I came with same question here and I realized that it was an XY problem. Reflection wasn't what I needed. – Bitterblue Nov 18 '13 at 12:08
  • 1
    I get this error "An unhandled exception of type 'System.InvalidCastException'" when casting to int (.Net 4.5). – Clay Lenhart Feb 27 '14 at 16:19
  • 4
    Not all enums are ints! Enums can also be sbyte, byte, short, ushort, uint, long, ulong, and char. You should cast to the underlying type, as the accepted answer suggests. – Anders Marzi Tornblad Oct 17 '14 at 07:17
  • Indeed, I updated my answer accordingly (at this point, Miltos' answer covered that too, but I'll make my answer more accurate nonetheless) – OLP Apr 20 '17 at 15:30
  • 1
    This is the answer I was looking for! It worked for me. Thanks :) – Najeeb Jul 25 '17 at 13:34
  • I like it when there is more code than only necessary plain English. – mtmk Apr 10 '19 at 09:18
25

Full code : How to Get Enum Values with Reflection in C#

MemberInfo[] memberInfos = 
        typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static);
string alerta = "";
for (int i = 0; i < memberInfos.Length; i++) {
    alerta += memberInfos[i].Name + " - ";
    alerta += memberInfos[i].GetType().Name + "\n";
}
Steve Friedl
  • 3,929
  • 1
  • 23
  • 30
Pranay Rana
  • 175,020
  • 35
  • 237
  • 263
  • 15
    I didn't -1, but I'd guess that even though the answer is correct, it's not very descriptive. Here's a link and some code, figure it out. It could be made better in a few ways, one of which would be to provide sample output. – John McDonald Sep 22 '13 at 20:27
6

If you have loaded an assembly in reflection-only context the methods GetValue and GetValues don't work. But we can use another approach:

var val = typeof(MyEnum).GetFields()
    .Where(fi => fi.IsLiteral && fi.Name == "TestOne")
    .Select(fi => fi.GetRawConstantValue())
    .First();
SergeyT
  • 800
  • 8
  • 15
3

Why do you need reflection?

int value = (int)TestEnum.TestOne;
Daniel A. White
  • 187,200
  • 47
  • 362
  • 445
3

For your requirement it's as simple as people already pointed it out. Just cast the enum object to int and you'd get the numeric value of the enum.

int value = (int) TestEnum.TestOne;

However, if there is a need to mix-down enum values with | (bitwise OR) e.g.

var value = TestEnum.TestOne | TestEnum.TestTwo;

and you wish to get what options that mixed-down value represents, here is how you could do it (note: this is for enums that represented by int values intended to take advantage of bitwise operatations) :

first, get the enum options along with their values in a dictionary.

var all_options_dic = typeof(TestEnum).GetEnumValues().Cast<object>().ToDictionary(k=>k.ToString(), v=>(int) v);

Filter the dictionary to return only the mixed-down options.

var filtered = all_options_dic.Where(x => (x.Value & (int) options) != 0).ToDictionary(k=>k.Key, v=>v.Value);

do whatever logic with your options. e.g. printing them, turning them to List, etc..:

foreach (var key in filtered.Keys)
        {
            Console.WriteLine(key + " = " + filtered[key]);
        }

hope this helps.

H7O
  • 859
  • 8
  • 5
2

Try the following:

System.Array enumValues = System.Enum.GetValues(typeof(MyEnum));
Type underlyingType = System.Enum.GetUnderlyingType(MyEnum);

foreach (object enumValue in enumValues)
    System.Console.WriteLine(String.Format("{0}",Convert.ChangeType(enumValue ,underlyingType)));
user2584621
  • 2,305
  • 2
  • 15
  • 9
1

You can use the Gethashkey function to get the value of enum with an unknown type.

Enum.Parse(enumType, enumvalue).GetHashCode();

More details

Getting enum type dynamically

  private static Type GetEnumType(string enumName)
    {
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                var type = assembly.GetType(enumName);
                if (type == null)
                    continue;
                if (type.IsEnum)
                    return type;
            }
        return null;
    }

Reading enum values

Enum.GetValues(enumType);

I hope it helps someone!

Shervin Ivari
  • 1,759
  • 5
  • 20
  • 28
1

Get enum int value via reflection using this method

protected static object PropertyValue(object obj, string propertyName)
{
  var property = obj.GetType().GetProperty(propertyName);
  if(property == null)
    throw new Exception($"{propertyName} not found on {obj.GetType().FullName}");

  if (property.PropertyType.IsEnum)
    return (int) property.GetValue(obj);
  return property.GetValue(obj);
}
Muhammad Ali
  • 173
  • 1
  • 6
0

Or, if you needed the actual enum object (of type TestEnum) :

MemberInfo[] memberInfos = typeof(MyEnum).GetMembers(BindingFlags.Public | BindingFlags.Static);
string alerta = "";
for (int i = 0; i < memberInfos.Length; i++) {

alerta += memberInfos[i].Name + " - ";


/* alerta += memberInfos[i].GetType().Name + "\n"; */ 

// the actual enum object (of type MyEnum, above code is of type System.Reflection.RuntimeFieldInfo)
object enumValue = memberInfos[i].GetValue(0);
alerta += enumValue.ToString() + "\n";
}
0

Just simple.

var value = propertyInfo.GetValue(obj);  // this return TestOne or TestTwo

var enumValue = Convert.ChangeType(value, typeof(int));  // this return 3 or 4 
Mong Zhu
  • 23,309
  • 10
  • 44
  • 76
Kim Ki Won
  • 1,795
  • 1
  • 22
  • 22
0

Hi you have this alternative:

Type typevar = GetType([YourEnum])

And then ... ... You can get names using typevar.GetEnumNames returning a array with names and to get values using type.GetEnumValues, returning an array with values.

dmr
  • 19
  • 9
0
System.Type.GetType("Namespace Name" + "." + "Class Name" + "+" + "Enum Name")

Dim fieldInfos() As System.Reflection.FieldInfo = System.Type.GetType("YourNameSpaceName.TestClass+TestEnum").GetFields

For Each f As System.Reflection.FieldInfo In fieldInfos 
    If f.IsLiteral Then 
        MsgBox(f.Name & " : " & CType(f.GetValue(Nothing), Integer) & vbCrLf) 
    End If 
Next 

Public Class TestClass
    Public Enum TestEnum
        val1 = 20
        val2 = 30
    End Enum
End Class

That works

The_Black_Smurf
  • 5,178
  • 14
  • 52
  • 78
-1

No need for reflection:

int value = (int)TestEnum.TestOne;
Fredrik Mörk
  • 155,851
  • 29
  • 291
  • 343
-1

In my case, the problem was MyEnum not been found due to a + sign getting type from assembly (line 2):

var dll = System.Reflection.Assembly.LoadFile("pathToDll");
Type myEnum = dll.GetType("namespace+MyEnum");
System.Array myEnumValues = System.Enum.GetValues(myEnum);
dbardelas
  • 354
  • 2
  • 13
-1

There must be a motivation to ask a question like this. Here I have one real life scenario with good motivation to do something like this and the solution to this problem.

Motivation

2 assemblies with circular references. One reference is hard reference, i.e. <Reference . . .> tag in project file. And a soft reference in opposite direction. assembly1 must call some object, some method in assembly2. Method's argument is enum

Here is the code that will get enum value. The assembly is already loaded at the time of calling this method because instance of the object containing method already loaded

Solution

internal static object GetEnumValue(string assemblyName, string enumName, string valueName) // we know all these 
{
    var assembly = Assembly.Load(assemblyName);
    var converter = new EnumConverter(assembly.GetType(enumName)); 
    object enumVal = converter.ConvertFromString(valueName);
    return enumVal;
}

And the usage

dynamic myInstance = GetInstanceOfKnownObject(.......); // this preloads assembly for first time. All sequential loads are easy
dynamic enumArg = GetEnumValue("assemblyName", "assembly2.namespace1.EnumName", "enumValueName"); // important to load into 'dynamic', not 'object'
myInstance.MyMethod(enumArg);

Bottom line - it is really useful when one assembly has no idea (and can't have knowledge) of the other assembly internals.

T.S.
  • 18,195
  • 11
  • 58
  • 78
  • Probably cause, like me, I don't understand how this answers this 8-year old question. – Rob Nov 09 '18 at 03:26
  • @Rob its not the answer that you don't understand, its the question. People constantly ask to retrieve enum value of the enum that is NOT known, i.e. enum from un-referenced assembly, which objects are called by reflection. Hence, enum needs to be retrieved by reflection. OP keeps repeating **"yet again I know how to do it this way. but I need to use reflection"**. Well, the question is not super-clear but you sense what OP is asking, I know where OP coming from. And this question been viewed 48K times, so its needed. And my answer explains how properly to do it, but also adds common scenario – T.S. Nov 09 '18 at 04:11