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?
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?
Pseudo code:
enum MyCountryEnum
{
UnitedKingdom = 0,
UnitedStates = 1,
France = 2,
Portugal = 3,
}
string[] shortCodes = new string[] {"UK", "US", "FR", "PO"};
MyCountryEnum enumValue = MyCountryEnum.UnitedKingdom;
string code = shortCodes[enumValue];
You could create an extension method public static string ToShortString(this Country country)
. In the method you could use either a static Dictionary as Jon suggests, or you could simply do a switch case.
Example:
public static class CountryExtensions
{
public static string ToShortString( this Country target )
{
switch (target) {
case Country.UnitedKingdom:
return "UK";
case Country.UnitedStates:
return "US";
case Country.France:
return "FR";
case Country.Portugal:
return "PT";
default:
return "None";
}
}
}
Just use the DescriptionAttribute
No need to create a dictionary if you only need to get a String representation for your enum values. See this example
[EDIT] Oh ... forgot to mention that it is more reusable than dictionaries, since you only need one common util class to help with getting the description and then all you need to do is add the DescriptionAttribute next time you add an enum value or you create a new enum with the same requirements. In the dictionary/switch solution, it is harder to maintain and it gets messy once you have many enum types.
var codes = new Dictionary<Country, string>()
{ { Country.UnitedKingdom, "UK" },
{ Country.UnitedStates, "US" },
{ Country.France, "FR" } };
Console.WriteLine(codes[Country.UnitedStates]);
I prefer to use the DescriptionAttribute on my enums. Then, you can use the following code to grab that description from the enum.
enum MyCountryEnum
{
[Description("UK")]
UnitedKingdom = 0,
[Description("US")]
UnitedStates = 1,
[Description("FR")]
France = 2,
[Description("PO")]
Portugal = 3
}
public static string GetDescription(this Enum value)
{
var type = value.GetType();
var fi = type.GetField(value.ToString());
var descriptions = fi.GetCustomAttributes(typeof(DescriptionAttribute), false) as DescriptionAttribute[];
return descriptions.Length > 0 ? descriptions[0].Description : value.ToString();
}
public static SortedDictionary<string, T> GetBoundEnum<T>() where T : struct, IConvertible
{
// validate.
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an Enum type.");
}
var results = new SortedDictionary<string, T>();
FieldInfo[] fieldInfos = typeof(T).GetFields();
foreach (var fi in fieldInfos)
{
var value = (T)fi.GetValue(fi);
var description = GetDescription((Enum)fi.GetValue(fi));
if (!results.ContainsKey(description))
{
results.Add(description, value);
}
}
}
And then to get my bound enum list, its simply a call to
GetBoundEnum<MyCountryEnum>()
To get a single enum's description, you'd just use the extension method like this
string whatever = MyCountryEnum.UnitedKingdom.GetDescription();
Whenever I see an enum I feel that the code should be refactored. Why not make a Country class and add methods to do some of the obstacles you are trying to get around. Assigning values to an enum is an even bigger code smell.
Why the downvotes? I think it is pretty widely accepted that using a polymorphic approach is better than using an enum. There is zero reason to use an enum when you can use the ValueObject design instead.
Here is a good blog post on the topic: http://devpinoy.org/blogs/cruizer/archive/2007/09/12/enums-are-evil.aspx
One other possibility that hasn't been mentioned is something like this:
public class Country
{
public static readonly Country UnitedKingdom = new Country("UK");
public static readonly Country UnitedStates = new Country("US");
public static readonly Country France = new Country("FR");
public static readonly Country Protugal = new Country("PT");
private Country(string shortName)
{
ShortName = shortName;
}
public string ShortName { get; private set; }
}
From this point you could add more properties, but beware of how much you add to the class, and how many static members you add, as the memory bloat it adds could make it not worth it.
I don't think there are many cases where this strategy is the best approach, but it is an option to be aware of when attempting to add properties or attributes to something you want to be able to treat as essentially an enum.
I had to leave my work on this project for a while, and having come back to it, I had a moment of inspiration.
Rather than an enum, I created a new class like so:
public class Country
{
public const string UnitedKingdom = "UK";
public const string France = "F";
}
This way I can use Country.UnitedKingdom in my code and the value "UK" will be used.
I'm just posting this answer as an alternative solution.
Neil