C# String Switch

String type

Switch works on strings. The C# language allows you to switch on a string variable. The switch is compiled in different ways depending on the cases. Switch has very simple syntax. It has performance implications.

Example

Switch

First we can use the switch statement for testing whether a string is one of a set of values. You can do this without manually creating any data structures such as an array or Dictionary.

ArrayDictionary

Tip:The C# compiler will try to improve the switch's performance based on an internal heuristic.

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

In this example, IsMoth contains a switch case with seven moth names in it. If any of those strings are equivalent to the parameter, it returns true and we know we have a moth name. And "Ash Pug" as a parameter results in true.

Bool Method

Internals

Framework: NET

String switches are sometimes compiled into a custom Dictionary. My experiments showed that in the case of previous example, having six 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

Result

Compiler generated a Dictionary.
Compiler generated a Dictionary.
Compiler generated series if/conditionals.

ToLower

Lowercase and uppercase words

Because switch cases must be constant, you cannot compare them case-insensitively without custom code. In this example, 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.

ToLower
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

Abbreviations

Programming tip

A switch can handle abbreviations or synonyms. It can resolve different words that mean the same thing. For example, in Excel spreadsheets, users will enter different column titles that mean the same thing.

So:I have used switches to tell the computer that "Height" is an abbreviation for "Ht.".

Trim

Trim string

Similar to using the ToLower method, you can use the Trim, TrimEnd, and TrimStart methods to try to normalize the input further. For example, you can use TrimEnd to remove a period on the end of a string before using it in the switch.

TrimTrimEndTrimStart

Benchmark

Performance optimization

Here we see a simple benchmark of a switch expression versus an if/else chain expression. In the example, the compiler turns the string switch shown first into a Dictionary of strings.

Note:The benchmark compares this compiler optimization against the if/else chain that is used in the final method.

If
Methods that were benchmarked: C#

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");
}

Code used in benchmark loops: C#

if (IsTree("Alder") &&
    IsTree("Persimmon") &&
    IsTree("???"))
{
    i++;
}

if (IsTreeExpression("Alder") &&
    IsTreeExpression("Persimmon") &&
    IsTreeExpression("???"))
{
    i++;
}
This section provides information

The result of the above benchmark is that the method using switch performed more than twice as slow as the method that uses the || expressions. The switch statement completed in 1340 ms, while the second method completed in 728 ms.

Also:I tried to make the benchmark fair by using the first and last possibilities as the first two arguments.

Benchmark

Notes:Switching on strings was slower in this test. Internally, switch was compiled to a Dictionary.

Result

Switch (7 strings): 1340 ms
If (7 strings):      728 ms [faster]

In theory, the optimization might work. If your switch statement has 100 strings in it, the switch keyword will likely outperform an if/else chain. But if you can reorder the if-statements in an optimal way, even this might not be true.

Reorder If-Statements

Summary

We saw examples of string switch statements. We saw how this can be used to resolve inconsistencies in user input, and test for specific string values. We saw how switches can be slower than if-statements.


C#: Switch