C# – Conditionally initializing a string list

cinitializationlistnet

I am writing a program that needs to be able to process data from a number of different sources. The sources output data in a variety of formats. So, depending on which source is being used, I need to initialize a string list with a different set of column headers. The quantity of headers varies between 10 and 18 columns depending on the data source.

Essentially, I need a clean method to conditionally initialize a list. I have three working solutions but I am not sure which is the cleanest/best practice:

  • Example #1 requires that I add each header to the list line-by-line. With the number of potential sources and columns that need to be added for each, this list gets pretty long.
  • Example #2 requires that I use {} around each case statement to limit the scope so that I can declare the dataHeaders list individually in each case statement. I have never encountered a situation wherein I had to limit the scope to an individual case statement and as such, I suspect it is bad practice.
  • Example #3 seems like the best option. I actually implemented this one as I was writing this question. I don't really see any drawbacks here but I thought I'd still pose the question anyhow.

Is there a better/cleaner way to do this? If not, which example is the best practice?

Example #1:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        headers.Add("header1");
        headers.Add("header2");
        headers.Add("header3");
        headers.Add("...");
        headers.Add("header18");
        break;
    case "Source 2":
        headers.Add("headerA");
        headers.Add("headerB");
        headers.Add("headerC");
        headers.Add("...");
        headers.Add("headerJ");
        break;
    default:
        // TODO: Handle bad sources.
        break;
}

Example #2:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        {
            List<string> dataHeaders = new List<string>() { "header1", "header2", "header3", "...", "header18" }
            headers = dataHeaders;
            break;
        }
    case "Source 2":
        {
            List<string> dataHeaders = new List<string>() { "headerA", "headerB", "headerC", "...", "headerJ" }
            headers = dataHeaders;
            break;
        }
    default:
        {
            // TODO: Handle bad sources.
            break;
        }
}

Example #3:

List<string> headers = new List<string>();
switch (dataSource)
{
    case "Source 1":
        headers.AddRange(new List<string>() { "header1", "header2", "header3", "...", "header18" })
        break;
    case "Source 2":
        headers.AddRange(new List<string>() { "headerA", "headerB", "headerC", "...", "headerJ" })
        break;
    default:
        // TODO: Handle bad sources.
        break;
}

Best Answer

A lot of times, you can really clean up a problem like this by expressing your data in a form with less syntax than a programming language, such as a CSV string. I don't know C#, but an example in Scala is:

def headersForDataSource(dataSource: String): Option[Array[String]] = {
  val headers = """
    Source1,header1,header2,header3,...,header18
    Source2,headerA,headerB,headerC,...,headerJ
    """

  val lines = headers.lines map (_.trim split ',')
  lines find (_(0) == dataSource) map (_.tail)
}

You can see this makes your list of headers significantly more compact and easier to read, because it doesn't clutter and intermingle it with the syntax of the data structure. It's putting it in your preferred format, instead of the format forced on you by the programming language.