C# String Switch ExamplesMatch string cases with a switch statement for improved performance. Test string literals.
String switch. Often we need to make a decision in code based on a string's value. We can test characters, or lengths, but sometimes we need to match entire strings.
Switch notes. With a switch statement, the C# compiler implements hidden optimizations to speed up matching. This can help programs go faster.
An example. Here we 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 will try to improve the switch's performance based on its internal heuristic.
IsMoth This method contains a switch case with 2 moth names in it. If any of those strings equal the parameter, it returns true.
using System; class Program { static void Main() { Console.WriteLine(IsMoth("Ash Pug")); Console.WriteLine(IsMoth("?")); } static bool IsMoth(string value) { switch (value) { case "Atlas Moth": case "Ash Pug": return true; default: return false; } } }
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]
ldsfld class [mscorlib]System.Collections.Generic.Dictionary ldsfld class [mscorlib]System.Collections.Generic.Dictionary L_000b: call bool [mscorlib]System.String::op_Equality
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.
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; } } }
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.
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; } } } }
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.
TrimEnd, TrimStart
Here We handle abbreviations in a string switch, and also remove ending spaces. Further string logic could be added.
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")); } }
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 On .NET 5 in 2021, switch is faster. If we cannot test for the most common string first, a string switch can improve performance.
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")); } 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"); } }
24.58 ns switch (IsTree) 62.49 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 summary. 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.
© 2007-2022 sam allen.
see site info on the changelog.