C# tutorials > Core C# Fundamentals > Basics and Syntax > How does the `switch` statement work in C#?

How does the `switch` statement work in C#?

The switch statement in C# is a selection control mechanism that allows a variable to be tested for equality against a list of values. Each value is called a 'case', and the variable being switched on is checked for a match against each case. When a match is found, the code block associated with that case is executed. It offers a more structured and readable alternative to multiple if-else if-else statements, especially when dealing with a discrete set of possible values.

Basic Syntax of a `switch` Statement

Here's a breakdown of the syntax:

  • switch (expression): The expression is evaluated once. The result is compared to the values in the case statements. The expression must evaluate to a type that can be implicitly converted to the type of each case label. Valid types include integer types, string, enum and char.
  • case constant_expression_n:: Each case represents a possible value of the expression. The constant_expression must be a constant value or a literal. It must be the same type as the expression or be implicitly convertible to it.
  • break;: The break statement terminates the switch statement and transfers control to the statement immediately following the switch. Before C# 7.0, it was generally required at the end of each case block. C# 7.0 introduced features that allow cases to fall through under certain conditions (see 'Alternatives' section).
  • default:: The default case is optional. It specifies the code to execute if no case matches the expression. If no default case exists and no case matches, then no code within the switch statement is executed.

switch (expression)
{
    case constant_expression_1:
        // statements to execute if expression == constant_expression_1
        break;
    case constant_expression_2:
        // statements to execute if expression == constant_expression_2
        break;
    ...
    default:
        // statements to execute if no case matches the expression
        break;
}

Example: Using `switch` with an Integer

This example demonstrates a simple switch statement that assigns a day name based on an integer value representing the day of the week. The day variable is evaluated, and the corresponding case is executed. If day is not a value between 1 and 7, the default case is executed.

int day = 3;
string dayName;

switch (day)
{
    case 1:
        dayName = "Monday";
        break;
    case 2:
        dayName = "Tuesday";
        break;
    case 3:
        dayName = "Wednesday";
        break;
    case 4:
        dayName = "Thursday";
        break;
    case 5:
        dayName = "Friday";
        break;
    case 6:
        dayName = "Saturday";
        break;
    case 7:
        dayName = "Sunday";
        break;
    default:
        dayName = "Invalid Day";
        break;
}

Console.WriteLine($"Day {day} is {dayName}"); // Output: Day 3 is Wednesday

Example: Using `switch` with a String

This example showcases the switch statement with a string. The fruit variable's value is compared to the string literals in the case statements. String comparisons are case-sensitive by default.

string fruit = "apple";
string color;

switch (fruit)
{
    case "apple":
        color = "red or green";
        break;
    case "banana":
        color = "yellow";
        break;
    case "orange":
        color = "orange";
        break;
    default:
        color = "unknown";
        break;
}

Console.WriteLine($"The color of {fruit} is {color}"); // Output: The color of apple is red or green

Concepts Behind the Snippet

The core concept behind the switch statement is to provide a clean and efficient way to handle multiple conditional branches based on the value of a single expression. It improves code readability and maintainability compared to deeply nested if-else structures. The switch statement works by comparing the expression's value to the values specified in each case. If a match is found, the corresponding block of code is executed. The default case acts as a catch-all for values that don't match any of the explicit case values.

Real-Life Use Case Section

Consider a scenario where you are developing a user interface with different types of controls (e.g., button, text box, label). When the user interacts with a control, you need to perform different actions based on the control type. A switch statement is ideal for handling this situation. Another example is parsing command-line arguments, where the action taken depends on the command entered by the user.

// Example use case: Handling different UI control types
string controlType = "button"; // Simulate the control type from user interaction

switch (controlType)
{
    case "button":
        Console.WriteLine("Button clicked!");
        // Perform button-specific actions here
        break;
    case "textBox":
        Console.WriteLine("Text box value changed.");
        // Perform text box-specific actions here
        break;
    case "label":
        Console.WriteLine("Label displayed.");
        // Perform label-specific actions here
        break;
    default:
        Console.WriteLine("Unknown control type.");
        // Handle unknown control types
        break;
}

Best Practices

  • Always include a default case to handle unexpected or invalid input.
  • Ensure that the break statement is present at the end of each case block (unless fall-through behavior is intentionally used - see Alternatives). Omitting the break can lead to unexpected execution.
  • Use a switch statement when dealing with a discrete set of possible values. For complex conditional logic, consider using if-else statements or other design patterns.
  • Use meaningful case labels to improve code readability.
  • When using string in a switch statement, be mindful of case sensitivity. Consider using .ToLower() or .ToUpper() if case-insensitivity is required.

Interview Tip

Be prepared to discuss the differences between switch statements and if-else statements. Explain when each is more appropriate. Also, understand the concept of 'fall-through' and how it's handled in C# 7.0 and later. Be ready to explain why including a default case is generally considered good practice.

When to Use Them

Use switch statements when you have a single variable that needs to be compared against multiple constant values. This makes the code more readable and maintainable than using a series of nested if-else statements. switch statements are particularly useful when dealing with enums, integer values, strings, or characters.

Alternatives

  • If-Else Statements: The traditional alternative to switch statements is a chain of if-else if-else statements. While they can achieve the same result, switch statements are often more readable and efficient, especially when dealing with a large number of cases.
  • Lookup Tables (Dictionaries): For more complex scenarios, especially when the 'cases' involve more than simple equality checks, consider using a dictionary or lookup table. This can be more flexible and scalable.
  • Fall-Through (C# 7.0 and later): C# 7.0 introduced features that allow cases to 'fall through' to the next case if the case block is empty. This requires the case block to be empty and is less common. It's often clearer to duplicate the code in each case or refactor to a common method. It's important to note that from C# 7 onward, cases can fall through when empty. Example:
    switch (value)
    {
        case 1:
        case 2:
            // Executes for both value 1 and 2
            Console.WriteLine("Value is 1 or 2");
            break;
        default:
            Console.WriteLine("Value is something else");
            break;
    }

Pros

  • Readability: switch statements can be more readable than long chains of if-else statements, especially when dealing with multiple discrete cases.
  • Efficiency: In some cases, compilers can optimize switch statements more effectively than if-else chains.
  • Structure: switch statements provide a structured way to handle multiple conditions based on a single variable.

Cons

  • Limited Expression Types: switch statements only work with a limited set of data types (integers, strings, enums, chars).
  • Constant Case Values: Case values must be constant values or literals. They cannot be variable expressions.
  • Break Statements: The requirement for break statements can sometimes lead to errors if they are accidentally omitted (though modern IDEs often provide warnings).
  • Less Flexible Conditions: switch statements are best suited for equality checks. For more complex conditions (e.g., range checks, logical combinations), if-else statements are generally more appropriate.

FAQ

  • What happens if no case matches the expression and there is no default case?

    If no case matches the expression and there is no default case, the switch statement does nothing. Control is simply transferred to the next statement after the switch block.
  • Can I use variables in the case labels?

    No, case labels must be constant expressions or literals. You cannot use variables directly in the case labels. The values must be known at compile time.
  • Are string comparisons in switch statements case-sensitive?

    Yes, string comparisons in switch statements are case-sensitive by default. If you need case-insensitive comparisons, you can use the ToLower() or ToUpper() methods on the string being switched on.
  • Why do I need a break statement in each case?

    The break statement is used to exit the switch statement after a matching case has been executed. Without a break statement, execution would 'fall through' to the next case, which is generally not the desired behavior (unless intentionally used using empty cases with fallthrough). In modern C#, you can also use return, throw, or goto to exit a case.