Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multi-variable switch statement in C#

I would like use a switch statement which takes several variables and looks like this:

switch (intVal1, strVal2, boolVal3)
{
   case 1, "hello", false:
      break;
   case 2, "world", false:
      break;
   case 2, "hello", false:

   etc ....
}

Is there any way to do something like this in C#? (I do not want to use nested switch statements for obvious reasons).

The question was answered by .net dev team by implementing of exactly this fearture: Multi-variable switch statement in C#

like image 216
BanditoBunny Avatar asked Nov 01 '11 13:11

BanditoBunny


People also ask

Can switch have 2 variables?

Yes as other state. You can have only one expression but that expression can have multiple variables. Although, for readability, we recommend put a simple expression in the switch.

Can switch case have multiple conditions in C?

A switch statement—or simply a case statement—is a control flow mechanism that determines the execution of a program based on the value of a variable or an expression. Using a switch statement allows you to test multiple conditions and only execute a specific block if the condition is true.

Can we pass multiple values in switch case?

Here is some important point of the switch statement in Java, have to follow. You can use N number of case values for a switch expression. The Case unit must be unique, otherwise, a compile-time error occurred.


3 Answers

You can do this in C# 7 and higher with the when keyword:

switch (intVal1)
{
    case 1 when strVal2 == "hello" && boolVal3 == false:
        break;
    case 2 when strVal2 == "world" && boolVal3 == false:
        break;
    case 2 when strVal2 == "hello" && boolVal3 == false:
        break;
}
like image 95
Stephen Kennedy Avatar answered Oct 20 '22 10:10

Stephen Kennedy


There is (was) no built-in functionality to do this in C#, and I don't know of any library to do this.

Here is an alternative approach, using Tuple and extension methods:

using System;

static class CompareTuple {
    public static bool Compare<T1, T2, T3>(this Tuple<T1, T2, T3> value, T1 v1, T2 v2, T3 v3) {
        return value.Item1.Equals(v1) && value.Item2.Equals(v2) && value.Item3.Equals(v3); 
    }
}

class Program {
    static void Main(string[] args) {
        var t = new Tuple<int, int, bool>(1, 2, false);
        if (t.Compare(1, 1, false)) {
            // 1st case
        } else if (t.Compare(1, 2, false)) {
            // 2nd case
        } else { 
            // default
        }
    }
}

This is basically doing nothing more than providing a convenient syntax to check for multiple values - and using multiple ifs instead of a switch.

like image 14
Paolo Tedesco Avatar answered Oct 20 '22 11:10

Paolo Tedesco


Let's look at this another way. If you have:

  • Very specific combinations you want to check for;
  • No comparisons to do;
  • A default handler for every non-matching case;
  • All primitive/value types (int, bool, string, etc.)

Then you can use a look-up table instead, which has a similar execution speed to the switch statement but not quite as efficient (since it needs to calculate hashes). Still, it's probably good enough. And it gives you the opportunity to name cases, to make this combinatorial explosion slightly less confusing and unmaintainable.

A code example:

private static readonly Tuple<int, int, bool> NameOfCase1 = 
    Tuple.Create(1, 1, false);
private static readonly Tuple<int, int, bool> NameOfCase2 =
    Tuple.Create(2, 1, false);
private static readonly Tuple<int, int, bool> NameOfCase3 =
    Tuple.Create(2, 2, false);

private static readonly Dictionary<Tuple<int, int, bool>, string> Results =
    new Dictionary<Tuple<int, int, bool>, string>
{
    { NameOfCase1, "Result 1" },
    { NameOfCase2, "Result 2" },
    { NameOfCase3, "Result 3" }
};

public string GetResultForValues(int x, int y, bool b)
{
    const string defaultResult = "Unknown";
    var lookupValue = Tuple.Create(x, y, b);
    string result;
    Results.TryGetValue(lookupValue, out result);
    return defaultResult;
}

If you need to actually execute a function or method for each case then you can use a result type (dictionary value) of Action<T> or Func<T> instead.

Note that I'm using Tuple<T1,T2,T3> here because it already has all of the hash code logic built in. The syntax is a little awkward in C# but if you want, you can implement your own lookup class and just override Equals and GetHashCode.

like image 12
Aaronaught Avatar answered Oct 20 '22 11:10

Aaronaught