Can I use a switch statement in conjunction with string.Contains()?
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.
BrianH
Updated on June 04, 2022Comments
-
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?