TheDeveloperBlog.com

Home | Contact Us

C-Sharp | Java | Python | Swift | GO | WPF | Ruby | Scala | F# | JavaScript | SQL | PHP | Angular | HTML

C# Switch Statements: Case and Goto

These C# examples cover the switch statement. It is possible to switch on value types and strings.

Switch. This construct tests a variable against a set of constants.

The compiler uses lookup table optimizations. A switch makes a decision. It is sometimes faster than if.

Example. This program uses a switch. It introduces an int local. It tests the int against two constants: 1 and 5. As it equals 5, we reach the second case. And 5 is printed.

Caution: Not every variable can be used in a switch. Most built-in value types, like int or char, work.

Strings: A switch can handle strings. These are implemented in a different way. They use a hidden Dictionary.

Based on:

.NET 4.5

C# program that uses switch

using System;

class Program
{
    static void Main()
    {
	int value = 5;
	switch (value)
	{
	    case 1:
		Console.WriteLine(1);
		break;
	    case 5:
		Console.WriteLine(5);
		break;
	}
    }
}

Output

5

Another example. This includes curly brackets and the default case. The program accepts an int from the user (with ReadLine). It then tests it for six values.

Here: We see how the curly brackets are used in the switch cases. And we combine some of the case statements.

C# program that uses int switch

class Program
{
    static void Main()
    {
	while (true)
	{
	    System.Console.WriteLine("Type number and press Return");
	    try
	    {
		int i = int.Parse(System.Console.ReadLine());
		switch (i)
		{
		    case 0:
		    case 1:
		    case 2:
			{
			    System.Console.WriteLine("Low number");
			    break;
			}
		    case 3:
		    case 4:
		    case 5:
			{
			    System.Console.WriteLine("Medium number");
			    break;
			}
		    default:
			{
			    System.Console.WriteLine("Other number");
			    break;
			}
		}
	    }
	    catch
	    {
	    }
	}
    }
}

Output

Type number and press Return
5
Medium number
Type number and press Return
2
Low number
Type number and press Return
500
Other number

Strings. Often we switch on values, like numbers. The contents of strings are not value types—they are collections of characters. But with special support, we switch on strings too.

Note: The C# compiler detects a string switch and can optimize it with a Dictionary lookup.

Note 2: Small string switches, like this one with just 3 cases, are often not compiled into Dictionaries. Performance is better this way.

C# program that switches on string

using System;

class Program
{
    static void Main()
    {
	string value = "turnip";
	// ... Switch on the string.
	switch (value)
	{
	    case "lettuce":
		Console.WriteLine("LETTUCE");
		break;
	    case "squash":
		Console.WriteLine("SQUASH");
		break;
	    case "turnip":
		Console.WriteLine("TURNIP");
		break;
	}
    }
}

Output

TURNIP

Types. It is possible to switch on integers or other value types, such as enums or chars. Strings are a reference type, but the C# compiler can handle switches on strings as well.

Switch CharSwitch EnumSwitch String

Case. We cover switch syntax. The switch statement uses somewhat different indentation rules by default. Some cases (default) do not use the case keyword.

Case

Goto. We can use goto statements in switches. These are different from other gotos. With goto we can run multiple cases for a single expression.

Goto, Switch

Break. This keyword is used within switches. And continue may also be used. These two keywords are used also within loops. Sometimes they are used in both loop and switch statements.

BreakContinue

So: Are you breaking out of a switch, or out of the enclosing loop? Scope is important: the deepest construct is broken first.

Double. Some values may not be switched upon. Floating-point values, like doubles, will cause an error in a switch expression. Most classes and custom types will also fail.

Bool: A bool may be used in the expression of a switch. But this is somewhat strange as only true and false are allowed.

Nullable: A nullable type can be used, but only if the nullable type "wraps" a valid switch type like an enum.

C# program that causes switch double error

class Program
{
    static void Main()
    {
	double value = 1.4;
	switch (value)
	{
	    case 1:
		break;
	}
    }
}

Output

Error 1
A switch expression or case label must be a bool, char, string,
integral, enum, or corresponding nullable type....

Nested switch. Sometimes one switch is not enough. But we can nest a switch within another switch, successively testing values. This approach is sometimes helpful.

Nested Switch

But: Our code logic, with nested switches, quickly turns into a mess. With comments, this approach may succeed.

Here: I test the first two elements in an int array with switches. The second element is tested if the first is 4.

C# program that uses nested switch

using System;

class Program
{
    static void Main()
    {
	int[] array = { 4, 10, 14 };
	switch (array[0])
	{
	    case 3:
		Console.WriteLine(3); // Not reached.
		break;

	    case 4:
		Console.WriteLine(4);
		// ... Use nested switch.
		switch (array[1])
		{
		    case 10:
			Console.WriteLine(10);
			break;
		}
		break;
	}
    }
}

Output

4
10

Fall through. Every case must have a break, continue, goto, return or throw at its end. In C# we cannot have cases with statements fall through to the following case.

Goto: We can use the goto statement, as in "goto case 1," to run both cases on a 0 value. As shown, the program does not compile.

C# program that has fall-through error

using System;

class Program
{
    static void Main()
    {
	int value = 0;
	// ... Every switch statement must be terminated.
	switch (value)
	{
	    case 0:
		Console.WriteLine("Zero");
	    case 1:
		Console.WriteLine("One");
		break;
	}
    }
}

Output

Error 1
Control cannot fall through from one case label ('case 0:') to another

Duplicate cases. A switch can only have unique case labels—each constant value must be distinct. This program will not compile. But it shows us what happens when we have duplicate cases.

C# that has duplicate case

using System;

class Program
{
    static void Main()
    {
	short number = 0;
	// ... Cases may not be duplicated.
	switch (number)
	{
	    case 0:
	    case 0:
		Console.WriteLine("ZERO");
		return;
	    case 1:
		Console.WriteLine("ONE");
		return;
	}
    }
}

Output

Error 1
The label 'case 0:' already occurs in this switch statement

Constants. We must use only constants for case statements. This is a limitation, but it is part of the language specification. The C# compiler is not even tempted.

C# that lacks constant case

using System;

class Program
{
    static void Main()
    {
	int number = 0;
	int test = 10;
	// ... Constant values are required.
	switch (number)
	{
	    case test + 1:
		Console.WriteLine(100);
		return;
	    case 0:
		Console.WriteLine(0);
		return;
	}
    }
}

Output

Error 1
A constant value is expected

Benchmark. A switch statement helps optimize some programs. Suppose a method that must return a value based on a small range of inputs. We can use switch to test these values.

Here: Method 1 uses a switch statement. But method 2 instead uses a series of if-statements.

Note: The benchmark shows that the switch statement version is slightly faster. Those nanoseconds may come in handy someday.

C# that benchmarks switch

using System;
using System.Diagnostics;

class Program
{
    static int Method1(int v)
    {
	switch (v)
	{
	    case 0:
		return 10;
	    case 1:
		return -1;
	    case 2:
		return 20;
	    default:
		return 0;
	}
    }

    static int Method2(int v)
    {
	if (v == 0) return 10;
	if (v == 1) return -1;
	if (v == 2) return 20;
	return 0;
    }

    static void Main()
    {
	Method1(0); Method2(0);
	const int max = 100000000;

	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < max; i++)
	{
	    Method1(0);
	    Method1(1);
	    Method1(2);
	    Method1(3);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < max; i++)
	{
	    Method2(0);
	    Method2(1);
	    Method2(2);
	    Method2(3);
	}
	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();
    }
}

Results

9.25 ns    [switch]
9.85 ns    [if]

Speed. Switch can be implemented with a jump table in the intermediate language. Large switches can be much faster than long series of if-else statements. We provide more benchmarks.

1. If and switch. The if-statement sometimes performs better than the switch. Testing is essential.

If, Switch Comparison

2. Regex and switch. The switch statement can be used to replace a Regex method call. This can make programs much faster.

Regex, Switch

3. Intermediate language: Switch is often implemented at a lower level with the switch opcode. We show an example.

IL: switch

Usage. Should we use switches everywhere? This is probably a bad idea. With polymorphism, we abstract selections with virtual methods and inheritance. This leads to cleaner code.

Virtual

So: If you want to use switches everywhere in your code, go ahead. But don't expect to be admired for it.

Refactoring. We consider a quote from the book Refactoring, an excellent treatise on how to improve code so it is not terrible. Well-designed code is easier to maintain.

The problem with switch statements is essentially that of duplication. Often you find the same switch statement scattered around a program in different places. If you add a new clause to the switch, you have to find all these switch statements and change them.

Refactoring: Improving the Design of Existing Code

My thoughts. Switches often outperform if-statements. But more importantly, they help with code design. They enforce all values tested are constants.

Symmetry. This construct imparts a greater sense of symmetry. Switches test value types and strings. They speed up selections. And with them, we write clearer code.


Related Links

Adjectives Ado Ai Android Angular Antonyms Apache Articles Asp Autocad Automata Aws Azure Basic Binary Bitcoin Blockchain C Cassandra Change Coa Computer Control Cpp Create Creating C-Sharp Cyber Daa Data Dbms Deletion Devops Difference Discrete Es6 Ethical Examples Features Firebase Flutter Fs Git Go Hbase History Hive Hiveql How Html Idioms Insertion Installing Ios Java Joomla Js Kafka Kali Laravel Logical Machine Matlab Matrix Mongodb Mysql One Opencv Oracle Ordering Os Pandas Php Pig Pl Postgresql Powershell Prepositions Program Python React Ruby Scala Selecting Selenium Sentence Seo Sharepoint Software Spellings Spotting Spring Sql Sqlite Sqoop Svn Swift Synonyms Talend Testng Types Uml Unity Vbnet Verbal Webdriver What Wpf