C# String Switch Examples

Match string cases with a switch statement for improved performance. Test string literals.
String switch. In the night sky a moth flutters its wings. It lands on a road sign. Imagine (just for a second) you are an entomologist. You are tracking moth populations.
Once data is collected, analysis begins. With a string switch statement in C# we can test strings (like names of moths or other flying insects). This even can impart a performance boost.
An example. A moth's name is just a string. We can use switch (on strings) to test whether a string is a moth name. Let's call our method that does this "IsMoth."

Tip: No fancy collections like a Dictionary or complex if-else chains are required here.

And: The C# compiler (our friend) will try to improve the switch's performance based on its internal heuristic (also known as magic).

IsMoth: Contains a switch case with 7 moth names in it. If any of those strings equal the parameter, it returns true. We have a moth name.

C# program that uses switch using System; class Program { static void Main() { Console.WriteLine(IsMoth("Ash Pug")); Console.WriteLine(IsMoth("Dot Net Perls")); } static bool IsMoth(string value) { switch (value) { case "Atlas Moth": case "Beet Armyworm": case "Indian Meal Moth": case "Ash Pug": case "Latticed Heath": case "Ribald Wave": case "The Streak": return true; default: return false; } } } Output True False
Internals. String switches are sometimes compiled into a custom Dictionary. Having 6 or more string cases and a default case resulted in the compiler generating a Dictionary.
Switch complexity 7 strings + default 6 strings + default 5 strings + default [and fewer] Compilation ldsfld class [mscorlib]System.Collections.Generic.Dictionary ldsfld class [mscorlib]System.Collections.Generic.Dictionary L_000b: call bool [mscorlib]System.String::op_Equality Output Compiler generated a Dictionary. Compiler generated a Dictionary. Compiler generated series if/conditionals.
ToLower. Switch cases must be constant. We cannot compare them case-insensitively without custom code. Here we normalize the string values with ToLower before entering the string switch.

Then: All the cases are lowercase. This results in a case-insensitive string switch.

Tip: The uppercase string "WHIPPET" was found to be a dog type. The value.ToLower() expression will match "whippet" in lowercase.

C# program that uses switch, ToLower using System; class Program { static void Main() { Console.WriteLine(IsDogCaseInsensitive("WHIPPET")); Console.WriteLine(IsDogCaseInsensitive("sphynx")); } static bool IsDogCaseInsensitive(string value) { switch (value.ToLower()) { case "irish terrier": case "jagdterrier": case "keeshond": case "sulimov dog": case "whippet": case "eurasier": case "brittany": return true; default: return false; } } } Output True False
Null case. Most switch cases in C# a red on values (like 10 or 20) or string literals. But with the string switch we can match the null literal.

Note: In .NET Framework internals, null is like a 0 value, so it too is a constant—we call it the null literal constant.

C# program that uses null case in switch using System; class Program { static void Main() { foreach (string value in new string[] { null, "" }) { switch (value) { case null: // Can have a null case. Console.WriteLine("CASE NULL"); break; case "": // Empty string case also works. Console.WriteLine("CASE EMPTY"); break; } } } } Output CASE NULL CASE EMPTY
Abbreviations. A switch can handle abbreviations or synonyms. For example, in Excel spreadsheets, users will enter different column titles that mean the same thing.

So: We can use switches to tell the computer that "Height" is an abbreviation for "Ht."

Trim: We can use the Trim, TrimEnd, and TrimStart methods to try to normalize the input further.

TrimTrimEnd, TrimStart

Here: We handle abbreviations in a string switch, and also remove ending spaces. Further string logic could be added.

C# program that uses switch with abbreviations, Trim method using System; class Program { static bool IsHeight(string value) { // Match the trimmed value and return a bool. switch (value.Trim()) { case "Ht.": case "Height": return true; } return false; } static void Main() { Console.WriteLine("HEIGHT: {0}", IsHeight("Height")); Console.WriteLine("HEIGHT: {0}", IsHeight("Ht. ")); Console.WriteLine("HEIGHT: {0}", IsHeight("Width")); } } Output HEIGHT: True HEIGHT: True HEIGHT: False
Benchmark. Here we test a string switch against an if-else chain expression. The C# compiler turns the string switch into a Dictionary of strings. Then, cases perform a Dictionary lookup.

Version 1: We use the string switch to test the tree name strings. The switch is run in a tight loop.

Version 2: We use an expression, which is compiled into something like a series of if-else statements.


Result: The string switch statement is faster. If we cannot test for the most common string first, a string switch can improve performance.

C# program that benchmarks string switch using System; using System.Diagnostics; class Program { const int _max = 100000000; static void Main() { string[] trees = new string[] { "Adler", "Persimmon", "???" }; int treeCount = 0; var s1 = Stopwatch.StartNew(); // Version 1: use string switch. for (int i = 0; i < _max; i++) { foreach (string tree in trees) { if (IsTree(tree)) { treeCount++; } } } s1.Stop(); var s2 = Stopwatch.StartNew(); // Version 2: use expression. for (int i = 0; i < _max; i++) { foreach (string tree in trees) { if (IsTreeExpression(tree)) { treeCount++; } } } s2.Stop(); Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) / _max).ToString("0.00 ns")); Console.Read(); } static bool IsTree(string value) { switch (value) { case "Alder": case "Elderberry": case "Chestnut": case "Guava": case "Willow": case "Elm": case "Persimmon": return true; default: return false; } } static bool IsTreeExpression(string value) { return (value == "Alder" || value == "Elderberry" || value == "Chestnut" || value == "Guava" || value == "Willow" || value == "Elm" || value == "Persimmon"); } } Output 32.94 ns switch (IsTree) 78.21 ns if (IsTreeExpression)
Result, above benchmark. In 2017, the switch version benchmarks faster. But here is an important point—in 2008 when I first tried this benchmark, the if-statement worked faster.

So: It may be useful to test the code on a system before you deploy it. Things might be wrong on the Internet.

Note: To achieve even better performance, you can try reordering the strings in an optimal way.

Tree: For complex situations where we have many strings and want to test them in a loop, consider a directed acyclic graph.

A review. A flying insect does not care about switch statements. But for data analysis of strings, we should care deeply about switch statements (and their syntax).
For performance, switches can be slower than if-statements. Often these small slowdowns do not matter. But when they do, an understanding of how switches work is important.Switch
© 2007-2020 Sam Allen. Every person is special and unique. Send bug reports to
Dot Net Perls