Getting Enum value via reflection

74,067

Solution 1

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.

Solution 2

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

Solution 3

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";
}

Solution 4

Why do you need reflection?

int value = (int)TestEnum.TestOne;

Solution 5

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();
Share:
74,067
mat-mcloughlin
Author by

mat-mcloughlin

Updated on July 19, 2022

Comments

  • mat-mcloughlin
    mat-mcloughlin almost 2 years

    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?

  • mat-mcloughlin
    mat-mcloughlin over 13 years
    ;) yeah I know how to do it this way. But I need to use reflection
  • mat-mcloughlin
    mat-mcloughlin over 13 years
    yet again I know how to do it this way. but I need to use reflection
  • Fredrik Mörk
    Fredrik Mörk over 13 years
    @mjmcloug: if you extend your question with brief information on why you need to use reflection and your use case, you will get better answers :)
  • Admin
    Admin over 11 years
    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.
  • Miltos Kokkonidis
    Miltos Kokkonidis over 11 years
    Thanks for the comment, but actually this is the answer to the question Mat was asking.
  • Miltos Kokkonidis
    Miltos Kokkonidis over 11 years
    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! :-)
  • Admin
    Admin over 11 years
    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.
  • Miltos Kokkonidis
    Miltos Kokkonidis over 11 years
    @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
    Miltos Kokkonidis over 11 years
    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?
  • G.Y
    G.Y about 11 years
    @MiltosKokkonidis Very elegant solution, helped me too :)
  • Skrymsli
    Skrymsli almost 11 years
    @MiltosKokkonidis I agree with the way you interpreted this question. Thanks for the solution.
  • John McDonald
    John McDonald over 10 years
    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.
  • mrmillsy
    mrmillsy over 10 years
    This one really deserves more +1
  • Bitterblue
    Bitterblue over 10 years
    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.
  • Clay Lenhart
    Clay Lenhart about 10 years
    It's because we don't know the type TestEnum, we just know we have an enum.
  • Clay Lenhart
    Clay Lenhart about 10 years
    I get this error "An unhandled exception of type 'System.InvalidCastException'" when casting to int (.Net 4.5).
  • Anders Marzi Tornblad
    Anders Marzi Tornblad over 9 years
    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.
  • OLP
    OLP about 7 years
    Indeed, I updated my answer accordingly (at this point, Miltos' answer covered that too, but I'll make my answer more accurate nonetheless)
  • zdarsky.peter
    zdarsky.peter almost 7 years
    After 2 miserable hours, I finally found this solution. Thanks a lot! :-)
  • Najeeb
    Najeeb almost 7 years
    This is the answer I was looking for! It worked for me. Thanks :)
  • T.S.
    T.S. over 5 years
    what if I don't have this info namespace.TestEnum but only have this "namespace.TestEnum"
  • Daniel A. White
    Daniel A. White over 5 years
    @T.S. you could use Type.GetType(yourString) to get the System.Type
  • T.S.
    T.S. over 5 years
    Only if its known/referenced type. But what if it is declared somewhere in other assembly?
  • Daniel A. White
    Daniel A. White over 5 years
    Assembly.Load[..](...) @T.S.
  • T.S.
    T.S. over 5 years
    Understand. However, this is not answered by your post. I actually posted real scenario where it is used stackoverflow.com/a/53218357/1704458
  • Daniel A. White
    Daniel A. White over 5 years
    @T.S. this answer/question is 8 years old. when i originally posted it, there was not a lot of context as to why reflection was needed. it was using the KISS principle.
  • Rob
    Rob over 5 years
    Probably cause, like me, I don't understand how this answers this 8-year old question.
  • T.S.
    T.S. over 5 years
    @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
  • ziya
    ziya about 5 years
    I like it when there is more code than only necessary plain English.