Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using collection of strings in a switch statement

I'm trying to find a solution for this problem. This is my example code:

class Program
{
  private string Command;

  private static string[] Commands = { "ComandOne", "CommandTwo", "CommandThree", "CommandFour" };


  static void Main(string[] args)
  {
    Command = args[0];
    switch(Command)
    {
      case Commands[0]: //do something 
        break;
      case Commands[1]: //do something else
        break;
      case Commands[2]: //do something totally different
        break;
      case Commands[3]: //do something boring
        break;
      default: //do your default stuff
        break;
    }
  }

  void DifferentMethod()
  {
    foreach(string c in Commands)
    {
      //do something funny
    }
  }
}

This code doesn't work because the string values in the switch are not constants. I want to write easy maintainable code.
I like to use something like an array because I need to use the same values somewhere else in a loop.
With int-values an enum would be perfect, but I didn't find a small solution for the same thing with strings.

like image 553
Philipp M Avatar asked Oct 01 '10 14:10

Philipp M


People also ask

Can you use strings with switch statements?

String is the only non-integer type which can be used in switch statement.

What is not allowed in a switch statement?

The switch statement doesn't accept arguments of type long, float, double,boolean or any object besides String.

What is a potential pitfalls of working with String variables within switch statement?

1. Expensive operation: Switching on strings can be more expensive in terms of execution than switching on primitive data types.


2 Answers

Convert Commands into an enum:

enum Commands { ComandOne, CommandTwo, CommandThree, CommandFour }

Switch statement should look like:

static void Main(string[] args)
{
    Command = (Commands)Enum.Parse(typeof(Commands), args[0]);
    switch(Command)
    {
        case Commands.CommandOne: 
            //do something 
            break;
        case Commands.CommandTwo: 
            //do something else
            break;
        ...
        default:
            // default stuff
    }
}

And your last method should look like:

void DifferentMethod()
{
    foreach(var c in Enum.GetValues(typeof(Commands)))
    {
        string s = c.ToString(); 
        //do something funny
    }
}
like image 97
Kirk Woll Avatar answered Oct 12 '22 22:10

Kirk Woll


An easy fix in your specific example:

switch(Array.IndexOf(Commands, Command))
{
    case 0: ...  
    case 1: ...

    default: //unknown command. Technically, this is case -1
} 

Other alternatives:

  1. Inline the strings.

    switch(Command) { case "CommandOne": ... case "CommandTwo": ... }

  2. Use an enumeration instead, as KirkWoll says. This is probably the cleanest solution.

  3. In more complex scenarios, using a lookup such as Dictionary<string, Action> or Dictionary<string, Func<Foo>> might provide better expressibility.

  4. If the cases are complex, you could create an ICommand interface. This will require mapping the command-string to the right concrete-implementation, for which you use simple constructs (switch / dictionaries) or fancy reflection (find ICommand implementations with that name, or with a certain attribute decoration).

like image 34
Ani Avatar answered Oct 12 '22 22:10

Ani