I have the following enumeration:
public enum AuthenticationMethod
{
FORMS = 1,
WINDOWSAUTHENTICATION = 2,
SINGLESIGNON = 3
}
The problem however is that I need the word "FORMS" when I ask for AuthenticationMethod.FORMS and not the id 1.
I have found the following solution for this problem (link):
First I need to create a custom attribute called "StringValue":
public class StringValue : System.Attribute
{
private readonly string _value;
public StringValue(string value)
{
_value = value;
}
public string Value
{
get { return _value; }
}
}
Then I can add this attribute to my enumerator:
public enum AuthenticationMethod
{
[StringValue("FORMS")]
FORMS = 1,
[StringValue("WINDOWS")]
WINDOWSAUTHENTICATION = 2,
[StringValue("SSO")]
SINGLESIGNON = 3
}
And of course I need something to retrieve that StringValue:
public static class StringEnum
{
public static string GetStringValue(Enum value)
{
string output = null;
Type type = value.GetType();
//Check first in our cached results...
//Look for our 'StringValueAttribute'
//in the field's custom attributes
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;
}
}
Good now I've got the tools to get a string value for an enumerator. I can then use it like this:
string valueOfAuthenticationMethod = StringEnum.GetStringValue(AuthenticationMethod.FORMS);
Okay now all of these work like a charm but I find it a whole lot of work. I was wondering if there is a better solution for this.
I also tried something with a dictionary and static properties but that wasn't better either.
I agree with Keith, but I can't vote up (yet).
I use a static method and swith statement to return exactly what I want. In the database I store tinyint and my code only uses the actual enum, so the strings are for UI requirements. After numerous testing this resulted in the best performance and most control over the output.
However, by some accounts, this leads to a possible maintenance nightmare and some code smell. I try to keep an eye for enums that are long and a lot of enums, or those that change frequently. Otherwise, this has been a great solution for me.
A lot of great answers here but in my case did not solve what I wanted out of an "string enum", which was:
1,2 & 4 can actually be solved with a C# Typedef of a string (since strings are switchable in c#)
3 can be solved by static const strings. So if you have the same needs, this is the simplest approach:
This allows for example:
and
Where CreateType can be called with a string or a type. However the downside is that any string is automatically a valid enum, this could be modified but then it would require some kind of init function...or possibly make they explicit cast internal?
Now if an int value was important to you (perhaps for comparison speed), you could use some ideas from Jakub Šturc fantastic answer and do something a bit crazy, this is my stab at it:
but of course "Types bob = 4;" would be meaningless unless you had initialized them first which would sort of defeat the point...
But in theory TypeA == TypeB would be quicker...
based on the MSDN: http://msdn.microsoft.com/en-us/library/cc138362.aspx
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
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.
As most of you, I really liked the selected answer by Jakub Šturc, but I also really hate to copy-paste code, and try to do it as little as I can.
So I decided I wanted an EnumBase class from which most of the functionality is inherited/built-in, leaving me to focus on the content instead of behavior.
The main problem with this approach is based on the fact that although Enum values are type-safe instances, the interaction is with the Static implementation of the Enum Class type. So with a little help of generics magic, I think I finally got the correct mix. Hope someone finds this as useful as I did.
I'll start with Jakub's example, but using inheritance and generics:
And here is the base class:
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.
Now if we try to call the above method we can call it this way
All you need to do is just create a resource file containing all the enumerator values and the corresponding strings
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!