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.
String is the only non-integer type which can be used in switch statement.
The switch statement doesn't accept arguments of type long, float, double,boolean or any object besides String.
1. Expensive operation: Switching on strings can be more expensive in terms of execution than switching on primitive data types.
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
}
}
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:
Inline the strings.
switch(Command) { case "CommandOne": ... case "CommandTwo": ... }
Use an enumeration instead, as KirkWoll says. This is probably the cleanest solution.
In more complex scenarios, using a lookup such as Dictionary<string, Action>
or Dictionary<string, Func<Foo>>
might provide better expressibility.
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).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With