21

Suppose I have a bunch of static fields and I want to use them in switch:

public static string PID_1 = "12";
public static string PID_2 = "13";
public static string PID_3 = "14";

switch(pid)
{
    case PID_1:
        //Do something 1
        break;
    case PID_2:
        //Do something 2
        break;
    case PID_3:
        //Do something 3
        break;
    default:
        //Do something default
        break;
}

Since C# doesn't allow non-const statement inside switch. I want to understand what is the intention of this kind of design. How should I do something like above in c#?

abatishchev
  • 98,240
  • 88
  • 296
  • 433
Ashutosh
  • 265
  • 1
  • 3
  • 12

7 Answers7

39

It looks like those string values should simply be constant.

public const string PID_1 = "12";
public const string PID_2 = "13";
public const string PID_3 = "14";

If that's not an option (they are actually changed at runtime), then you can refactor that solution into a series of if/else if statements.

As to why the case statements need to be constant; by having them be constant it allows the statement to be much more heavily optimized. It is actually more efficient than a series of if/else if statements (although not dramatically so if you don't have lots of conditional checks that take a long time). It will generate the equivalent of a hash table with the case statement values as keys. That approach couldn't be used if the values can change.

Servy
  • 202,030
  • 26
  • 332
  • 449
  • Ok. so why can't we use readonly fields? using const is not an option. Having a public static makes more sense for constant identifiers.. I can't use them anywhere I want and I just have one instance of it... – Ashutosh Sep 14 '12 at 18:49
  • 3
    @Ashutosh You can't use readonly fields because the value isn't known until runtime; the `switch` statement will result in a table being generated at *compile time*, which is why the case statements all need to be compile time constants. `"Having a public static makes more sense"` If the values are actually constant I disagree. Using a `const` value makes much more sense if the values are actually constant. Note that all `const` values are effectively `static`. They aren't tied to an instance of the object at all. – Servy Sep 14 '12 at 19:01
27

I know this is an old question but there is a way that wasnt covered in the other answers that doesnt involve changing the approach:

switch(pid)
{
   case var _ when pid == PID_1:
      //Do something 1
   break;
}
Mr Wood
  • 619
  • 7
  • 10
4

Case argument should be constant on compile-time.

Try to use const instead:

public const string PID_1 = "12";
public const string PID_2 = "13";
public const string PID_3 = "14";
H H
  • 263,252
  • 30
  • 330
  • 514
abatishchev
  • 98,240
  • 88
  • 296
  • 433
4

... C# doesn't allow non-const statement inside switch...

If you can't use:

public const string PID_1 = "12";
public const string PID_2 = "13";
public const string PID_3 = "14";

You can use a dictionary :)

....
public static string PID_1 = "12";
public static string PID_2 = "13";
public static string PID_3 = "14";



// Define other methods and classes here

void Main()
{
   var dict = new Dictionary<string, Action>
   {
    {PID_1, ()=>Console.WriteLine("one")},
    {PID_2, ()=>Console.WriteLine("two")},
    {PID_3, ()=>Console.WriteLine("three")},
   };
   var pid = PID_1;
   dict[pid](); 
}
OscarRyz
  • 196,001
  • 113
  • 385
  • 569
1

I'm assuming there's a reason you didn't declare those variables as const. That said:

The switch statement is just shorthand for a bunch of if / else if statements. So if you can guarantee that PID_1, PID_2, and PID_3 will never be equal, the above is equivalent to this:

if (pid == PID_1) {
    // Do something 1
}
else if (pid == PID_2) {
    // Do something 2
}
else if (pid == PID_3) {
    // Do something 3
}
else {
    // Do something default
}
egrunin
  • 24,650
  • 8
  • 50
  • 93
  • Switching on strings could also be implemented as a dictionary (https://stackoverflow.com/a/3366497/616827). – Jeff Jul 26 '17 at 21:27
1

The canonical way to approach this -- if your static fields are not actually constants -- is to use a Dictionary<Something, Action>:

static Dictionary<string, Action> switchReplacement = 
    new Dictionary<string, Action>() {
        { PID_1, action1 }, 
        { PID_2, action2 }, 
        { PID_3, action3 }};

// ... Where action1, action2, and action3 are static methods with no arguments

// Later, instead of switch, you simply call
switchReplacement[pid].Invoke();
Joshua Honig
  • 12,925
  • 8
  • 53
  • 75
1

Why you don't use enum ?
Enum keyword:
http://msdn.microsoft.com/en-us/library/sbbt4032%28v=vs.80%29.aspx

In your case it can be easily handled over enum:

public enum MyPidType
{
  PID_1 = 12,
  PID_2 = 14,
  PID_3 = 18     
}