How to use c# tuple value types in a switch statement

SoftAllan picture SoftAllan · Jun 4, 2017 · Viewed 9.6k times · Source

I'm using the new tuple value types in .net 4.7. In this example I am trying to make a switch statement for one or more cases of a tuple:

using System;
namespace ValueTupleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            (char letterA, char letterB) _test = ('A','B');
            Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'");

            switch (_test)
            {
                case ('A', 'B'):
                    Console.WriteLine("Case ok.");
                    break;
            }

        }
    }
}

This does not compile unfortunately.

How do I take a tuple and make cases in a switch statement correctly?

Answer

Yeldar Kurmangaliyev picture Yeldar Kurmangaliyev · Jun 5, 2017

Answering your question technically, you could use when to check tuple's values:

(char letterA, char letterB) _test = ('A', 'B');
Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'");

switch (_test)
{
    case var tuple when tuple.letterA == 'A' && tuple.letterB == 'B':
        Console.WriteLine("Case ok.");
        break;
    case var tuple when tuple.letterA == 'D' && tuple.letterB == '\0':
        Console.WriteLine("Case ok.");
        break;
}

However, consider using if version because it may be a more readable and understandable solution.

Another side of this question is single responsibility. Your methods knows what do A and B, D and \0 characters mean which breaks the single-responsibility principle.
In terms of OOP, it is better to separate this knowledge from you main code into a separate method.
Something like that could make code a little cleaner:

private static bool IsCaseOk(char a, char b) 
{
    return (a == 'A' && b == 'B') || (a == 'D' && b == '\0'); // any logic here
}

public static void Main() 
{
    (char letterA, char letterB) _test = ('A', 'B');
    Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'");

    if (IsCaseOk(_test.letterA, _test.letterB)) {
        Console.WriteLine("Case ok.");
    } else {
        Console.WriteLine("Case not ok.");
    }
}

If these letters have any meaning in your domain, then probably it is a better idea to even create a class with two char properties and encapsulate this logic there.