The Switch Statement Detailed Explanation in C#


C# switch statement is fundamental control flow structure in C#, which runs different code blocks upon the value of a variable or expression. Expecally when you happen to have multiple potential values, it’s a cleaner and more organized alternative to using any sets of if-else statements. In other words, it’s important to understand both basic and advanced usage of C# in order to write efficient and readable code.

In this article, we’ll go through how to use the switch statement on a deeper level, from its basic syntax to advanced features of it in recent .NET versions, accompanied with illustrative examples to help you get a better understanding.

Basic Usage

The switch statement is at its core a case block that is used when an expression is evaluated and then the executed case block which matches the result of the evaluated expression. With switch, the expression in parentheses and syntax follows. Inside a switch block we define cases using the case keyword, then a value and a colon.

Here’s the basic structure:

switch (expression)
{
    case value1:
        // Code block
        break;
    case value2:
        // Code block
        break;
    default:
        // Default code block
        break;
}

Each case is potential value of the expression. Break statement helps avoiding that the program continue the execution of the following cases, thus called “fall through”. Although optional, it is recommended as the default case; the default case is run when no case matches the expression.

With switch statement, code is easier to read, and maintain also. It combines some related conditionnal branches and makes the code more robust than many if else statements.

Example

Let’s consider a simple example where we map numerical month values to their corresponding month names:

int month = 5;
string monthName;

switch (month)
{
    case 1:
        monthName = "January";
        break;
    case 2:
        monthName = "February";
        break;
    case 3:
        monthName = "March";
        break;
    case 4:
        monthName = "April";
        break;
    case 5:
        monthName = "May";
        break;
    case 6:
        monthName = "June";
        break;
    case 7:
        monthName = "July";
        break;
    case 8:
        monthName = "August";
        break;
    case 9:
        monthName = "September";
        break;
    case 10:
        monthName = "October";
        break;
    case 11:
        monthName = "November";
        break;
    case 12:
        monthName = "December";
        break;
    default:
        monthName = "Invalid month";
        break;
}

Console.WriteLine($"The month is {monthName}.");

Here the switch statement in this example will check the value of month and take appropriate course of action. In case month equals 5, monthName is assigned “May”, the switch block ends with breaking out of it. By default case, if month has a value outside 1, 2, 3, …, to 12, monthName is set to ‘Invalid month’.

It also reduces tremendous amount of code when compared with multiple if else, and it provides clarity on output to each input values.

Advanced Usage

The switch statement has seen the evolution of C# making it more flexible and more powerful. Where C# 7.0 made a big advance was in pattern matching with switch statements, which makes it possible to write more nuanced evaluations than simple value comparison.

Pattern Matching

The switch statement allows pattern matching to check the value’s type, the structure and the properties. You can use type patterns, constant patterns and even mix patterns with logical operators.

object data = 42;

switch (data)
{
    case int number:
        Console.WriteLine($"It's an integer: {number}");
        break;
    case string text:
        Console.WriteLine($"It's a string: {text}");
        break;
    case null:
        Console.WriteLine("It's null");
        break;
    default:
        Console.WriteLine("Unknown type");
        break;
}

Here data is checked at runtime using switch statement. When an int is data, then we are in the first case, and the captured value is number. In the second case, if data is a string it matches. The pattern matching that this type makes easier for type checking and casting, and in result it helps to make code more concise and readable.

When Clauses

Also, once you have case with a given condition, you can then further refine cases using when clauses, which helps you to specify another condition(s).

int age = 25;

switch (age)
{
    case int n when n >= 0 && n <= 12:
        Console.WriteLine("Child");
        break;
    case int n when n >= 13 && n <= 19:
        Console.WriteLine("Teenager");
        break;
    case int n when n >= 20 && n <= 64:
        Console.WriteLine("Adult");
        break;
    case int n when n >= 65:
        Console.WriteLine("Senior");
        break;
    default:
        Console.WriteLine("Invalid age");
        break;
}

The when clauses add a condition to each case allowing for range checking on the switch statement. That means eliminating nested if statements and having straight forward control flow.

Switch Expressions

Suitably, switch expressions are introduced with C# 8.0 to reduce the amount of syntax for returning values depending on conditions. Just like any other expressions, switch expressions are expressions, not statements, and return a value directly.

string grade = "B";

string result = grade switch
{
    "A" => "Excellent",
    "B" => "Good",
    "C" => "Average",
    "D" => "Below Average",
    "F" => "Fail",
    _ => "Invalid grade"
};

Console.WriteLine($"Your performance is: {result}");

In this example grade is the value of the switch expression and result is the value of result that is assigned the corresponding string. The syntax with => drops case and break keywords and _ is used as default case.

Switch expressions cut down on boilerplate and generally make the code clearer if we are working with simple mappings or computations.

Switch Statement through .NET Versions

The switch statement had been around in C# since its inception (albeit with some shortcomings), and more recently the .NET versions have had the switch statement enhanced to support more and advanced programming paradigms.

Early Versions

In the early versions of C# the switch statement was limited to constant value comparisons with integral types, char, string and enumeration types. The cases had to be a constant expression; pattern matching or range conditions were not supported.

Therefore, the limitation was that developers often relied on multiple if-else in order to handle complex conditional, or non constant values, which made coding less readable as well as harder to maintain.

C# 7.0 introduces Pattern Matching

Pattern matching in switch statement was introduced to C# 7.0 by C# 7.0 with Visual Studio 2017 and .NET Framework 4.7. This addition therefore enabled developers to do type checks and bind variables inside the switch cases.

Switch statement had the expressiveness and power because of pattern matching and made previously cumbersome or even impossible scenarios possible in the traditional switch syntax.

Switch Expressions (C# 8.0)

Switch expressions were introduced with C# 8.0. Released on .NET Core 3.0 and .NET Standard 2.1. The expressive power of the switch construct was modernized by introducing the capability to use it as an expression that produces a value, rather than merely controlling flow.

Switch expressions eliminate the need for break statements, plus the ability to pattern match to values inside the switch. They match these functional programming practices that aim at immutability and expression based code.

C# 9.0 and Beyond

In subsequent versions of C# pattern matching in switch expressions has been further enhanced. Relational patterns and logical patterns were also baked into C# 9.0 enabling even more concise and powerful condition expressions.

As an example, relational patterns allow us to do things like <, <=, > and >= directly in switch cases.

int temperature = 75;

string weather = temperature switch
{
    < 32 => "Freezing",
    >= 32 and < 50 => "Cold",
    >= 50 and < 70 => "Mild",
    >= 70 and < 90 => "Warm",
    >= 90 => "Hot",
    _ => "Unknown"
};

Console.WriteLine($"The weather is {weather}.");

The reason for this is extremely clear and a perfect example of a driven logic coupled with a relational pattern to define the weather description by temperature. Its syntax is clean with an expressive structure showing how far the C# switch statement keeps changing.

Advanced Feature Example

For the sake of example, let’s consider a more complicated example which uses multiple pattern matching techniques using the switch statement in our modern C#.

public abstract class Shape { }

public class Circle : Shape
{
    public double Radius { get; set; }
}

public class Rectangle : Shape
{
    public double Height { get; set; }
    public double Width { get; set; }
}

public class Triangle : Shape
{
    public double Base { get; set; }
    public double Height { get; set; }
}

public static double ComputeArea(Shape shape) => shape switch
{
    Circle c => Math.PI * c.Radius * c.Radius,
    Rectangle r => r.Height * r.Width,
    Triangle t => 0.5 * t.Base * t.Height,
    _ => throw new ArgumentException("Unknown shape")
};

Shape myShape = new Circle { Radius = 5 };
double area = ComputeArea(myShape);
Console.WriteLine($"The area is {area}.");

The ComputeArea method of this example, calculates the area for different shapes using a switch expression. It does this by matching the specific shape type to leverage type patterns in order to access its properties. Switch expression makes what would otherwise span multiple if-else statements, peppered with type checks and casts, much simpler.

The simplicity of modern switch statements to handle complex logic is shown by this approach.

Conclusion

From a simple control flow mechanism to a powerful, pattern matching, and expression based programming tool, C#’s switch statement has grown over the years. It comes with those advanced features which afford the developers to write clear, readable and maintainable code.

Modern C# development involves knowing basic and advanced uses of the switch statement. The switch statement, either mapping values, checking types, or handling tricky conditions, is a useful tool that simplifies your code without sacrificing readability or readability.

Maintaining yourself up to date with the improvements done in past versions of .NET will allow you to take advantage of all the characteristics that the switch statement provides to make your apps robust and good looking.

,