Can I use a switch statement in conjunction with string.Contains()?

12,004

Solution 1

No, switch statements require constant values for the case labels. So in general you'd be better off sticking with the if statements. But this is about as close as you can get to using a switch statement for your scenario.

string myString = "ABC";
List<string> subStrings = new List<string>{"A", "B", "C"};
switch (subStrings.FirstOrDefault(myString.Contains))
{
    case "A":
        Console.WriteLine("Has A");
        break;
    case "B":
        Console.WriteLine("Has B");
        break;
    case "C":
        Console.WriteLine("Has C");
        break;
    default:
        Console.WriteLine("No ABC");
        break;
}

I doubt that would be any faster than the if statements, because the FirstOrDefault is basically doing the same thing, and it breaks the DRY principal as it requires updates to the list and switch statement.

Solution 2

Using the pattern matching feature in C# 7.0, it is now possible to use Contains in switch statements. Provides much cleaner code than multiple if else blocks. The following code sample shows how to do it

        var patterns = new[] { "dog", "cat", "cats and dogs", "parrot", "parrot and cat" };

        foreach (var item in patterns)
        {
            switch (item)
            {
                case var s when s.Contains("cat"):
                    Console.WriteLine($"{item} contains cat");
                    break;

                case var s when s.Contains("dog"):
                    Console.WriteLine($"{item} contains dog");
                    break;

                case var s when s.Contains("parrot"):
                    Console.WriteLine($"{item} contains parrot");
                    break;
            }
        }

Please note, it won't work with versions earlier than C# 7.0.

Solution 3

having a ton of if/else checks for specific stuff, usually alerts me of a good place to use enumerables for flexibility later if you can use it in your scenario. i'd probably do something like this:

string input = "ABDE";
var mapping = new Dictionary<Func<string, bool>, Action<string>>()
{
    { (string i) => i.Contains("A"), (string i) => Console.WriteLine("Found input with 'A'") },
    { (string i) => i.Contains("B"), (string i) => Console.WriteLine("Found input with 'B'") },
    { (string i) => i.Contains("C"), (string i) => Console.WriteLine("Found input with 'C'") },
    { (string i) => i.Contains("D"), (string i) => Console.WriteLine("Found input with 'D'") }
};

foreach (var criteria in mapping)
{
    if (criteria.Key(input)) {
        criteria.Value(input);
        break;
    }
}

That way the test/action conditions are grouped together, you can cleanly run over all the rules with a foreach without much work, and adding/removing rules is easier.

Share:
12,004
BrianH
Author by

BrianH

Updated on June 04, 2022

Comments

  • BrianH
    BrianH almost 2 years

    I have a method using a long string of if/elseif statements (about 10-15), and I understand that when you get past about 5 if/else if statements, it's better to use a switch. That being said, I'm not sure that I can use a switch statement in my case, because my if/else if statements rely on testing a string, not for equality, but using the Contains() method. So, right now I have something equivalent of

    string s = "ABCD";
    if(s.Contains("A")
    {
        //do stuff
    }
    else if(s.Contains("E")
    {
        //do different stuff
    }
    etc ...
    

    I've tried differnt ways of implementing the switch statement, such as

    switch()
    {
        case(s.Contains("A"))
        {
            //do stuff
        }
    }
    

    But each way I've tried results in a syntax error.

    Is there a way to use a switch statement while still testing the string using the Contains() method?