Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Getting Enum values

I have a enum containing the following (for example):

  • UnitedKingdom,
  • UnitedStates,
  • France,
  • Portugal

In my code I use Country.UnitedKingdom but I want to have the value be UK if I assign it to a string for example.

Is this possible?

like image 393
neildeadman Avatar asked Jun 17 '09 16:06

neildeadman


1 Answers

You can't assign an enum value to a string to start with. You'd have to call ToString(), which would convert Country.UnitedKingdom to "UnitedKingdom".

Two options suggest themselves:

  • Create a Dictionary<Country, string>
  • A switch statement
  • Decorate each value with an attribute, and load that with reflection

Comments about each of them...

Sample code for Dictionary<Country,string>

using System; using System.Collections.Generic;  enum Country {     UnitedKingdom,      UnitedStates,     France,     Portugal }  class Test {     static readonly Dictionary<Country, string> CountryNames =         new Dictionary<Country, string>     {         { Country.UnitedKingdom, "UK" },         { Country.UnitedStates, "US" },     };      static string ConvertCountry(Country country)      {         string name;         return (CountryNames.TryGetValue(country, out name))             ? name : country.ToString();     }      static void Main()     {         Console.WriteLine(ConvertCountry(Country.UnitedKingdom));         Console.WriteLine(ConvertCountry(Country.UnitedStates));         Console.WriteLine(ConvertCountry(Country.France));     } } 

You might want to put the logic of ConvertCountry into an extension method. For example:

// Put this in a non-nested static class public static string ToBriefName(this Country country)  {     string name;     return (CountryNames.TryGetValue(country, out name))         ? name : country.ToString(); } 

Then you could write:

string x = Country.UnitedKingdom.ToBriefName(); 

As mentioned in the comments, the default dictionary comparer will involve boxing, which is non-ideal. For a one-off, I'd live with that until I found it was a bottleneck. If I were doing this for multiple enums, I'd write a reusable class.

Switch statement

I agree with yshuditelu's answer suggesting using a switch statement for relatively few cases. However, as each case is going to be a single statement, I'd personally change my coding style for this situation, to keep the code compact but readable:

public static string ToBriefName(this Country country)  {     switch (country)     {         case Country.UnitedKingdom:  return "UK";         case Country.UnitedStates:   return "US";         default:                     return country.ToString();     } } 

You can add more cases to this without it getting too huge, and it's easy to cast your eyes across from enum value to the return value.

DescriptionAttribute

The point Rado made about the code for DescriptionAttribute being reusable is a good one, but in that case I'd recommend against using reflection every time you need to get a value. I'd probably write a generic static class to hold a lookup table (probably a Dictionary, possibly with a custom comparer as mentioned in the comments). Extension methods can't be defined in generic classes, so you'd probably end up with something like:

public static class EnumExtensions {     public static string ToDescription<T>(this T value) where T : struct     {         return DescriptionLookup<T>.GetDescription(value);     }      private static class DescriptionLookup<T> where T : struct     {         static readonly Dictionary<T, string> Descriptions;          static DescriptionLookup()         {             // Initialize Descriptions here, and probably check             // that T is an enum         }          internal static string GetDescription(T value)         {             string description;             return Descriptions.TryGetValue(value, out description)                 ? description : value.ToString();         }     } } 
like image 189
Jon Skeet Avatar answered Oct 23 '22 04:10

Jon Skeet