views:

280

answers:

8

Hi. I have enum like this:

public enum ObectTypes
{
    TypeOne,
    TypeTwo,
    TypeThree,
    ...
    TypeTwenty
 }

then I need to convert this enum to string. Now Im doing this that way:

public string ConvertToCustomTypeName(ObjectTypes typeObj)
{
    string result = string.Empty;
    switch (typeObj)
    {
        case ObjectTypes.TypeOne: result = "This is type T123"; break;
        case ObjectTypes.TypeTwo: result = "Oh man! This is type T234"; break;
        ...
        case ObjectTypes.TypeTwenty: result = "This is type last"; break;
    }
    return result;
}

Im quite sure that there is better way do do this, Im looking for some good practice solution.

EDIT: There is no one pattern in result string.

Thanks in advance.

+1  A: 

I think the easiest way is to have a function which maps between the enum value and the preferred short name and then create another function which generates the full message.

internal static string MapToName(ObjectTypes value) {
  switch (value) { 
    case ObjectTypes.TypeOne: return "T123";
    case ObjectTypes.TypeTwo: return "T234";
    ...
  }
}

public string ConvertToCustomTypeName(ObjectTypes value) {
  return String.Format("This is type {0}", MapToName(value));
}
JaredPar
It's obvious he wants to convert it to some arbitrary string, not the name of the enum field.
Matti Virkkunen
@Matti, thanks missed that. Updated answer
JaredPar
@JaredParThe prefix isnt' constant, the suffix isn't constant too, so I cant predict start of the string.
dario
@dario, can you give us some more examples then? It's hard to answer the question based on this limited sample
JaredPar
@JaredPar. Sure, examples below:"Cramshaft T124", "Low signal S", "High signal", "Overboost 1E", "Check engine!", "Fatal error", "Unknown", etc.
dario
+12  A: 

I use the [Description] attribute from System.ComponentModel

Example:

public enum RoleType
{
    [Description("Allows access to public information")] Guest = 0,
    [Description("Allows access to the blog")] BlogReader = 4,
}

Then to read from it I do

public static string ReadDescription<T>(T enumMember)
{
    var type = typeof (T);

    var fi = type.GetField(enumMember.ToString());
    var attributes = (DescriptionAttribute[]) 
            fi.GetCustomAttributes(typeof (DescriptionAttribute), false);
    return attributes.Length > 0 ? 
        attributes[0].Description : 
        enumMember.ToString();
}

Then usage

ReadDescription(RoleType.Guest);

Chris Marisic
This is awfully slow - may or may not matter, depending on the usage.
Reed Copsey
Premature optimization is the devil. If performance is a serious consideration you can implement caching and only ever need to read each enum member once. I use this to populate drop down lists so I cache singleton copies of my Code/Value pair enums in my model after I iterate over the enum once. If I was concerned about the reflection cost I would actually cache it inside the ReadDescription method in somekind of dictionary or hashtable etc.
Chris Marisic
This is a great technique for dealing with enums, although it would be a lot cleaner if the enum itself had a `GetDescription` method or some such (and if you could put the description *after* the enumeration).
MusiGenesis
I have all of these methods in a static class for working with Enums however I might try making them extension methods instead. So I can directly do `RoleType.Guest.ReadDescription()` instead of `EnumParser.ReadDescription(RoleType.Guest)`
Chris Marisic
Too bad you can't inherit from `enum`. I'd love to see the extension method version, if you've got the motivation. I'll pay you back with a drive-by.
MusiGenesis
@MusiGenisis: `enum` types inherit from `System.Enum`.
Simon Buchan
This method is also not culture aware. This is okay if you will ever only ship in one language, but as soon as you either require a different language or one customer requests a customisation, you end up having to keep another copy of the compiled dll.
slugster
+7  A: 

If you need a custom string, the best option would be to make a Dictionary< ObjectTypes, string>, and just do a dictionary lookup.

If you're fine with the default ToString() functionality, just use typeObj.ToString();

For the dictionary approach, you could do:

private static Dictionary<ObjectTypes, string> enumLookup;

static MyClass()
{
    enumLookup = new Dictionary<ObjectTypes, string>();
    enumLookup.Add(ObjectTypes.TypeOne, "This is type T123");
    enumLookup.Add(ObjectTypes.TypeTwo, "This is type T234");
    // enumLookup.Add...

}

Your method becomes:

public string ConvertToCustomTypeName(ObjectTypes typeObj)
{
     // Shouldn't need TryGetValue, unless you're expecting people to mess  with your enum values...
     return enumLookup[typeObj];
}
Reed Copsey
I feel the need to point out that for compact enums (no large value gaps), a List<string> would be much more efficient.
Simon Buchan
@Simon: Yes, potentially - although this is more flexible, for any value type in the enum, with any arbitrary enum value...
Reed Copsey
@Simon: Although, that's only true, too, if the enum values start at or near 0... You start getting "values" that can't easily be converted into list indices, and the hashing will be faster.
Reed Copsey
+1  A: 

I once used a custom attribute on the enum fields that took a string parameter and then wrote a function to extract the string when given an enum value.

Matti Virkkunen
Huh, didn't know enum members were attributable :).
Simon Buchan
A: 

This calls for refactoring, I'd say.

Replace Type Code With Class

David Hedlund
I don't necessarily agree with this, that would be over kill if it's really an enumeration that has code values and display values. I frequently use Enums to populate DropDowns.
Chris Marisic
+1  A: 

If you simply want to use the name of enum (ie TypeOne ) you can simply call ToString() on the enum itself

typeObj.ToString()

If you want a custom string based on the type you have several different options. The switch statement you have is OK but maintaining it will get messy if you have a large number of enums. Or you could setup a dictionary based using the enum type as the key and the string as the value.

public enum ObectTypes
{
   One,
   Two
}

Dictionary<ObectTypes, String> myDic = new Dictionary<ObectTypes, string>();
myDic.Add( ObectTypes.One, "Something here for One" );
myDic.Add( ObectTypes.Two, "Something here for Two" );
Justin
+2  A: 

I can't quite believe this... why has nobody suggested a Resource file?

Mapping enum values to strings within compiled code is all well and good as a quick hack, but long term it is a bad practice and makes it difficult to refactor code. What if you add (or subtract) a value from the enum? If you use strings from a resource file all you have to do is add (or remove) one entry.

slugster
I don't think many C# programmers use the resource file. It seems to be C++/win32/MFC coders who see the light of the resource file.
Justin
@Justin - i agree, not enough people are using them, possibly a bad habit left over from the old days of doing VB6 code etc. I think also as more people become aware of properly separating UI from the business logic (i.e. the MVVM pattern) then people will start using resource files more, especially as the resource files can be utilised as part of static binding.
slugster
+2  A: 

Use the suggested Resources way:

string GetName(Enum e) {
     return Properties.Resources.ResourcesManager.GetString("_enum_"+e.GetType().ToString().Replace('.','_'));
}

Error handling is a bit more..

Pasi Savolainen