views:

82

answers:

5

Okay, here's what I'm attempting.

I have a drop down list with all of the countries in the world. The user selects one, and that value is passed to a case statement, if it matches the case, an email is sent.

I only have four different recipents, but I can have upwards to dozens of countries to match with each one of the four emails. For example:

switch (selectedCountry)
{
    case "ca":
        sendTo = canadaEmail;
        break;
    case "uk":
    case "de":
    case "fr"
        sendTo = europeanEmail;
        break;
    case "bb":                
        sendTo = barbadosEmail;
        break;
    default:
        sendTo = usEmail;
        break;
}

What I would like to know is, what's a better way of doing this rather than having one huge case statement?

+4  A: 

You can use a dictionary instead:

Dictionary<string, string> sendToEmails = new Dictionary<string, string>();
sendToEmails["bb"] = barbadosEmail;
sendToEmails["ca"] = canadaEmail;
sendToEmails["uk"] = europeanEmail;
sendToEmails["de"] = europeanEmail;

Then use TryGetValue to get the value when you need it:

string sendTo;
if (sendToEmails.TryGetValue(selectedCountry, out sendTo))
{
    // Send the email here.
}

One advantage of this method is that your dictionary doesn't have to be hard coded into your program. It could just as easily come from a configuration file or a database.

If you choose the database route you could also consider using LINQ:

string sendTo = dc.CountryEmails
                  .SingleOrDefault(c => c.Country == selectedCountry);
Mark Byers
Hm, that's pretty much what the compiler ends up doing anyways with the `case` statement.
Lucero
Not necessarily. Small switch statements may be compiled as if/else chains. Plus, I agree that this might be appropriate for a config file.
Matthew Flaschen
I went this way at first, but found that having a one to one mapping would create a very large list of mappings. I went with the generic list because it would give me a much mor condensed version of this. Thanks for the suggestions.
Chris
A: 

Externalize it (XML, database, whatever you like...) and only implement a "state machine" which chooses the right one.

Lucero
+1  A: 

A couple options that would eliminate the cases:

  1. Store the mappings in a database and look them up by country code.
  2. Build a map in your code with the country code as the key and the email as the value.
Eric Petroelje
A: 

Yes -- if you have a hard coded list somewhere, consider using a collection of a custom type:

public class MyType
{
    public string Code { get; set; }
    public string Email { get; set; }
}

Then you could do something like this:

List<MyType> myList = new List<MyType>()
{
    new MyType() { Code = "A", Email = "something" },
    // etc..
}

string emailAddress = myList.Where(m => m.Code == selectedCountry);

Although, I'd say this is very poor design and I would encourage you to use a rdbms of some sort.

Ian P
+2  A: 

You can't get around the fact that somewhere, somehow, you'll have to enumerate the countries and assign them to an email address. You could do that in any number of ways, be it a database, an external XML file, or an internal List object.

For example:

List<string> europeanEmailCountries = new List<string>();
europeanEmailCountries.AddRange("fr", "de"); // etc

...

if(europeanEmailCountries.Contains(countryCode))
{
    sendTo = europeanEmailAddress;
}

This saves you the convoluted switch statement by allowing you to define a list of countries mapped to a particular email address, without going through each potential entry. I might be inclined to populate the list from an XML file instead of hardcoding the values, though.

TeeBasins
Working with a string array and a handfull of List<String> lists worked out great for me. It allowed me to add in a single array of all associated countries to the list, and then just pass in my dropdown value to the .Contains method. Worked well. Thanks!
Chris
Great - Glad I could help! :)
TeeBasins