I have the following enumeration:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
T
I use an extension method:
public static class AttributesHelperExtension
{
public static string ToDescription(this Enum value)
{
var da = (DescriptionAttribute[])(value.GetType().GetField(value.ToString())).GetCustomAttributes(typeof(DescriptionAttribute), false);
return da.Length > 0 ? da[0].Description : value.ToString();
}
}
Now decorate the enum
with:
public enum AuthenticationMethod
{
[Description("FORMS")]
FORMS = 1,
[Description("WINDOWSAUTHENTICATION")]
WINDOWSAUTHENTICATION = 2,
[Description("SINGLESIGNON ")]
SINGLESIGNON = 3
}
When you call
AuthenticationMethod.FORMS.ToDescription()
you will get "FORMS"
.
When I'm confronted with this problem, there are a couple of questions that I try to find the answers to first:
The simplest way to do this is with Enum.GetValue
(and support round-tripping using Enum.Parse
). It's also often worth building a TypeConverter
, as Steve Mitcham suggests, to support UI binding. (It's not necessary to build a TypeConverter
when you're using property sheets, which is one of the nice things about property sheets. Though lord knows they have their own issues.)
In general, if the answers to the above questions suggest that's not going to work, my next step is to create and populate a static Dictionary<MyEnum, string>
, or possibly a Dictionary<Type, Dictionary<int, string>>
. I tend to skip the intermediate decorate-the-code-with-attributes step because what's usually coming down the pike next is the need to change the friendly values after deployment (often, but not always, because of localization).
In your question you never said that you actually need the numeric value of the enum anywhere.
If you do not and just need an enum of type string (which is not an integral type so can not be a base of enum) here is a way:
static class AuthenticationMethod
{
public static readonly string
FORMS = "Forms",
WINDOWSAUTHENTICATION = "WindowsAuthentication";
}
you can use the same syntax as enum to reference it
if (bla == AuthenticationMethod.FORMS)
It will be a bit slower than with numeric values (comparing strings instead of numbers) but on the plus side it is not using reflection (slow) to access the string.
How I solved this as an extension method:
using System.ComponentModel;
public static string GetDescription(this Enum value)
{
var descriptionAttribute = (DescriptionAttribute)value.GetType()
.GetField(value.ToString())
.GetCustomAttributes(false)
.Where(a => a is DescriptionAttribute)
.FirstOrDefault();
return descriptionAttribute != null ? descriptionAttribute.Description : value.ToString();
}
Enum:
public enum OrderType
{
None = 0,
[Description("New Card")]
NewCard = 1,
[Description("Reload")]
Refill = 2
}
Usage (where o.OrderType is a property with the same name as the enum):
o.OrderType.GetDescription()
Which gives me a string of "New Card" or "Reload" instead of the actual enum value NewCard and Refill.
based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
foreach (string str in Enum.GetNames(typeof(enumHeaderField)))
{
Debug.WriteLine(str);
}
str will be the names of the fields
When I am in a situation like that I propose the solution below.
And as a consuming class you could have
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MyApp.Dictionaries
{
class Greek
{
public static readonly string Alpha = "Alpha";
public static readonly string Beta = "Beta";
public static readonly string Gamma = "Gamma";
public static readonly string Delta = "Delta";
private static readonly BiDictionary<int, string> Dictionary = new BiDictionary<int, string>();
static Greek() {
Dictionary.Add(1, Alpha);
Dictionary.Add(2, Beta);
Dictionary.Add(3, Gamma);
Dictionary.Add(4, Delta);
}
public static string getById(int id){
return Dictionary.GetByFirst(id);
}
public static int getByValue(string value)
{
return Dictionary.GetBySecond(value);
}
}
}
And using a bidirectional dictionary: Based on this (https://stackoverflow.com/a/255638/986160) assuming that the keys will be associated with single values in the dictionary and similar to (https://stackoverflow.com/a/255630/986160) but a bit more elegant. This dictionary is also enumerable and you can go back and forth from ints to strings. Also you don't have to have any string in your codebase with the exception of this class.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
namespace MyApp.Dictionaries
{
class BiDictionary<TFirst, TSecond> : IEnumerable
{
IDictionary<TFirst, TSecond> firstToSecond = new Dictionary<TFirst, TSecond>();
IDictionary<TSecond, TFirst> secondToFirst = new Dictionary<TSecond, TFirst>();
public void Add(TFirst first, TSecond second)
{
firstToSecond.Add(first, second);
secondToFirst.Add(second, first);
}
public TSecond this[TFirst first]
{
get { return GetByFirst(first); }
}
public TFirst this[TSecond second]
{
get { return GetBySecond(second); }
}
public TSecond GetByFirst(TFirst first)
{
return firstToSecond[first];
}
public TFirst GetBySecond(TSecond second)
{
return secondToFirst[second];
}
public IEnumerator GetEnumerator()
{
return GetFirstEnumerator();
}
public IEnumerator GetFirstEnumerator()
{
return firstToSecond.GetEnumerator();
}
public IEnumerator GetSecondEnumerator()
{
return secondToFirst.GetEnumerator();
}
}
}