views:

177

answers:

4

I'm trying to avoid hardcoding in a .net 2.0 soon to be 3.5 application.

I have a large enumeration which I wish to map 1 to 1 to a set of strings. Each enumerated value will also map to 1 of 2 values indicating an action. The existing code does this with a big switch statement but this seems ugly to me.

Is there a better way of storing and accessing the data?

I've thought about resx files but when you consider that the designer file contains just as many hardcoded values it seems a little pointless.

Is embedding an xml file in the assembly a good idea?

Is a big switch statement not as bad as it seems?

Is there a better solution?

A: 

Despite how ugly a switch statement is its the most efficient way to map enums to strings. Embedding an XML file will just bloat the size of your assembly and it will take much longer to get the string value you need.

ChaosPandion
While not ideal i decided this is probably the simplest solution.
haymansfield
+1  A: 

You can use the Enum description attribute to assign a string to each enum value. I don't know if it's more efficient than a switch statement but it does have the advantage of assigning the string value in the same place in code that the enum is defined.

CodeProject has an article here. There's also a good example here.

TLiebe
These are both good ideas for mapping the string but I also need to map to a second 2 value property which I can't do with your solutions.
haymansfield
You could always define your own custom attributes. See http://msdn.microsoft.com/en-us/library/aa288454%28VS.71%29.aspx. The only problem is that you need to use reflection to get the values so it probably won't be as efficient as a switch statement.
TLiebe
Reflection should only be used only if there is no other option due to the performance hit.
Evan Plaice
A: 

Also see the answers to this question.

IMHO, big switch statements are ALWAYS a code smell, and are impossible to maintain.

SWeko
These are both good ideas for mapping the string but I also need to map to a second 2 value property which I can't do with your solutions.
haymansfield
Well, use another dictionary, or use a `Dictionary<Enum, YourCustomMappingType>`
SWeko
A: 

Using an enum in this case is trying to fit a square peg in a round hole. Whereas XML is overkill for what you're trying to do.

Use a dictionary instead. That way, there is a direct 'key => value' relationship and the value can be anything.

For the 1-1 string string relationship use this:

Dictionary<string, string> dictA = new Dictionary<string, string>();
dictA.Add("string1", "value1");
dictA.Add("string2", "value2");
dictA.Add("string3", "value3");

To access all of the values of the dictionary use this:

foreach (KeyValuePair<string, string> item in dictA)
{   
    Console.WriteLine("Key: {0}; Value: {1};", item.Key, item.Value);
}

If you need a 1-2 1-3 or 1-n string relationship use this:

Dictionary<string, List<string>> dictB = new Dictionary<string, List<string>>();
dictB.Add("string1", new List<string>() {"value1A", "value1B"});
dictB.Add("string2", new List<string>() {"value2A", "value2B"});
dictB.Add("string3", new List<string>() {"value3A", "value3B"});

To access all of the values of the dictionary use this:

foreach (KeyValuePair<string, List<string>> item in dictB)
{   
    Console.WriteLine("Key: {0}; Values: {1}, {2};", item.Key, item.Value[0], item.Value[1]);
}

If you need a staggered array relationship use this:

Dictionary<string, List<string>> dictB = new Dictionary<string, List<string>>();
dictB.Add("string1", new List<string>() {"value1A", "value1B, value1C"});
dictB.Add("string2", new List<string>() {"value2A", "value2B, value2C, value2D"});
dictB.Add("string3", new List<string>() {"value3A", "value3B"});

To access all of the values of the dictionary use this:

foreach (KeyValuePair<string, List<string>> item in dictB)
{   
    string values = "";
    int valLen = ((List<string>)item.Value).Count;
    for (int i = 0; i < valLen; i++)
    {
        if (i == (valLen - 1))
        {
            values += item.Value[i] + "";
        }
        else
        {
            values += item.Value[i] + ", ";
        }
    }
    Console.WriteLine("Key: {0}; Values: {1};", item.Key, values);
}

To get the value for a specific key do something like this:

string match = "string2";
if (dictD.ContainsKey(match))
{
    Console.WriteLine("The value for Key='{0}' is: '{1}'", match, dictD[match]);
}

An Enums is nothing but a glorified Dictionary. That's why you won't see them in a lot of other languages (especially dynamically typed languages).

Evan Plaice