I have the following enumeration:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
T
Use method
Enum.GetName(Type MyEnumType, object enumvariable)
as in (Assume Shipper
is a defined Enum)
Shipper x = Shipper.FederalExpress;
string s = Enum.GetName(typeof(Shipper), x);
There are a bunch of other static methods on the Enum class worth investigating too...
old post but...
The answer to this may actually be very simple. Use Enum.ToString() function
There are 6 overloads of this function, you can use Enum.Tostring("F") or Enum.ToString() to return the string value. No need to bother with anything else. Here is a working Demo
Note that this solution may not work for all compilers (this demo does not work as expected) but at least it works for the latest compiler.
Unfortunately reflection to get attributes on enums is quite slow:
See this question: Anyone know a quick way to get to custom attributes on an enum value?
The .ToString()
is quite slow on enums too.
You can write extension methods for enums though:
public static string GetName( this MyEnum input ) {
switch ( input ) {
case MyEnum.WINDOWSAUTHENTICATION:
return "Windows";
//and so on
}
}
This isn't great, but will be quick and not require the reflection for attributes or field name.
C#6 Update
If you can use C#6 then the new nameof
operator works for enums, so nameof(MyEnum.WINDOWSAUTHENTICATION)
will be converted to "WINDOWSAUTHENTICATION"
at compile time, making it the quickest way to get enum names.
Note that this will convert the explicit enum to an inlined constant, so it doesn't work for enums that you have in a variable. So:
nameof(AuthenticationMethod.FORMS) == "FORMS"
But...
var myMethod = AuthenticationMethod.FORMS;
nameof(myMethod) == "myMethod"
I use the Description attribute from the System.ComponentModel namespace. Simply decorate the enum and then use this code to retrieve it:
public static string GetDescription<T>(this object enumerationValue)
where T : struct
{
Type type = enumerationValue.GetType();
if (!type.IsEnum)
{
throw new ArgumentException("EnumerationValue must be of Enum type", "enumerationValue");
}
//Tries to find a DescriptionAttribute for a potential friendly name
//for the enum
MemberInfo[] memberInfo = type.GetMember(enumerationValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(DescriptionAttribute), false);
if (attrs != null && attrs.Length > 0)
{
//Pull out the description value
return ((DescriptionAttribute)attrs[0]).Description;
}
}
//If we have no description attribute, just return the ToString of the enum
return enumerationValue.ToString();
}
As an example:
public enum Cycle : int
{
[Description("Daily Cycle")]
Daily = 1,
Weekly,
Monthly
}
This code nicely caters for enums where you don't need a "Friendly name" and will return just the .ToString() of the enum.
Well, after reading all of the above I feel that the guys have over complicated the issue of transforming enumerators into strings. I liked the idea of having attributes over enumerated fields but i think that attributes are mainly used for Meta-data, but in your case i think that all you need is some sort of localization.
public enum Color
{ Red = 1, Green = 2, Blue = 3}
public static EnumUtils
{
public static string GetEnumResourceString(object enumValue)
{
Type enumType = enumValue.GetType();
string value = Enum.GetName(enumValue.GetType(), enumValue);
string resourceKey = String.Format("{0}_{1}", enumType.Name, value);
string result = Resources.Enums.ResourceManager.GetString(resourceKey);
if (string.IsNullOrEmpty(result))
{
result = String.Format("{0}", value);
}
return result;
}
}
Now if we try to call the above method we can call it this way
public void Foo()
{
var col = Color.Red;
Console.WriteLine (EnumUtils.GetEnumResourceString (col));
}
All you need to do is just create a resource file containing all the enumerator values and the corresponding strings
Resource Name Resource Value Color_Red My String Color in Red Color_Blue Blueeey Color_Green Hulk Color
What is actually very nice about that is that it will be very helpful if you need your application to be localized, since all you need to do is just create another resource file with your new language! and Voe-la!
You can reference the name rather than the value by using ToString()
Console.WriteLine("Auth method: {0}", AuthenticationMethod.Forms.ToString());
The documentation is here:
http://msdn.microsoft.com/en-us/library/16c1xs4z.aspx
...and if you name your enums in Pascal Case (as I do - such as ThisIsMyEnumValue = 1 etc.) then you could use a very simple regex to print the friendly form:
static string ToFriendlyCase(this string EnumString)
{
return Regex.Replace(EnumString, "(?!^)([A-Z])", " $1");
}
which can easily be called from any string:
Console.WriteLine("ConvertMyCrazyPascalCaseSentenceToFriendlyCase".ToFriendlyCase());
Outputs:
Convert My Crazy Pascal Case Sentence To Friendly Case
That saves running all the way around the houses creating custom attributes and attaching them to your enums or using lookup tables to marry an enum value with a friendly string and best of all it's self managing and can be used on any Pascal Case string which is infinitely more reusable. Of course, it doesn't allow you to have a different friendly name than your enum which your solution does provide.
I do like your original solution though for more complex scenarios though. You could take your solution one step further and make your GetStringValue an extension method of your enum and then you wouldn't need to reference it like StringEnum.GetStringValue...
public static string GetStringValue(this AuthenticationMethod value)
{
string output = null;
Type type = value.GetType();
FieldInfo fi = type.GetField(value.ToString());
StringValue[] attrs = fi.GetCustomAttributes(typeof(StringValue), false) as StringValue[];
if (attrs.Length > 0)
output = attrs[0].Value;
return output;
}
You could then access it easily straight from your enum instance:
Console.WriteLine(AuthenticationMethod.SSO.GetStringValue());