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.
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.
Here The IsMoth() 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
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 "BLUE" was found to be a color. The value.ToLower() expression will match "blue" in lowercase.
using System;
class Program
{
static void Main()
{
Console.WriteLine(IsColorCaseInsensitive("BLUE"));
Console.WriteLine(IsColorCaseInsensitive("red"));
}
static bool IsColorCaseInsensitive(string value)
{
switch (value.ToLower())
{
case "blue":
case "red":
case "yellow":
case "green":
return true;
default:
return false;
}
}
}True
True
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;
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;
}
}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."
Also We can use the Trim, TrimEnd, and TrimStart methods to try to normalize the input further.
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"));
}
}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 On .NET 7 in 2022, performance is about the same for both versions. In previous years, switch was faster here.
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");
}
}20.14 ns switch (IsTree)
21.33 ns if (IsTreeExpression)
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.
Dot Net Perls is a collection of tested code examples. Pages are continually updated to stay current, with code correctness a top priority.
Sam Allen is passionate about computer languages. In the past, his work has been recommended by Apple and Microsoft and he has studied computers at a selective university in the United States.