tags:

views:

668

answers:

3

I have an enum with Description attributes like this:

public enum MyEnum
{
    Name1 = 1,
    [Description("Here is another")]
    HereIsAnother = 2,
    [Description("Last one")]
    LastOne = 3
}

I found this bit of code for retrieving the description based on an Enum

public static string GetEnumDescription(Enum value)
{
    FieldInfo fi = value.GetType().GetField(value.ToString());

    DescriptionAttribute[] attributes =
        (DescriptionAttribute[])fi.GetCustomAttributes(
        typeof(DescriptionAttribute),
        false);

    if (attributes != null &&
        attributes.Length > 0)
        return attributes[0].Description;
    else
        return value.ToString();
}

This allows me to write code like:

var myEnumDescriptions = from MyEnum n in Enum.GetValues(typeof(MyEnum))
                         select new { ID = (int)n, Name = Enumerations.GetEnumDescription(n) };

What I want to do is if I know the enum value (e.g. 1) - how can I retrieve the description? In other words, how can I convert an integer into an "Enum value" to pass to my GetDescription method?

+4  A: 
int value = 1;
string description = Enumerations.GetEnumDescription((MyEnum)value);

The default underlying data type for an enum in C# is an int, you can just cast it.

Nicholas Piasecki
perfect. Exactly what I wanted. I knew it was going to be simple! Now, if stackoverflow would just let me accept this answer... it says I need to wait 7 minutes.
davekaro
+3  A: 

You can't easily do this in a generic way: you can only convert an integer to a specific type of enum. As Nicholas has shown, this is a trivial cast if you only care about one kind of enum, but if you want to write a generic method that can handle different kinds of enums, things get a bit more complicated. You want a method along the lines of:

public static string GetEnumDescription<TEnum>(int value)
{
  return GetEnumDescription((Enum)((TEnum)value));  // error!
}

but this results in a compiler error that "int can't be converted to TEnum" (and if you work around this, that "TEnum can't be converted to Enum"). So you need to fool the compiler by inserting casts to object:

public static string GetEnumDescription<TEnum>(int value)
{
  return GetEnumDescription((Enum)(object)((TEnum)(object)value));  // ugly, but works
}

You can now call this to get a description for whatever type of enum is at hand:

GetEnumDescription<MyEnum>(1);
GetEnumDescription<YourEnum>(2);
itowlson
How is "GetEnumDescription<MyEnum>(1);" any better than GetEnumDescription((MyEnum)1); ?
davekaro
@davekaro: Implemented like this, it's not all that much better, but a more robust implementation based on generics could do this without the explicit cast, so you don't risk unhandled exceptions if the number doesn't actually match any of the enum values.
Aaronaught
Interesting. Just to clarify for future readers: One is not going to get an unhandled exception on an explicit cast if the number doesn't match one of the enum values (you could say "MyEnum value = (MyEnum)5;" and that line will execute just fine, but you would bomb in the first line of GetEnumDescription() as implemented in the original question (because GetField() will return null as it can find no matching field with that value). (To guard against that, we'd need to check Enum.IsDefined() first and return null or an empty string, or just throw an ArgumentOutOfRangeException ourselves.)
Nicholas Piasecki
+1  A: 

I implemented this in a generic, type-safe way in Unconstrained Melody - you'd use:

string description = Enums.GetDescription((MyEnum)value);

This:

  • Ensures (with generic type constraints) that the value really is an enum value
  • Avoids the boxing in your current solution
  • Caches all the descriptions to avoid using reflection on every call
  • Has a bunch of other methods, including the ability to parse the value from the description

I realise the core answer was just the cast from an int to MyEnum, but if you're doing a lot of enum work it's worth thinking about using Unconstrained Melody :)

Jon Skeet
Isn't "value" an int? So, doesn't Enums.GetDescription((MyEnum)value) just cast the int to MyEnum?
davekaro
@davekaro: It casts the int to MyEnum - but you wouldn't be able to call it with any non-enum, including an "Enum" reference. Basically it's like your code, but with some generics magic.
Jon Skeet