Switch Expressions (Modern C#)
Vaibhav • September 9, 2025
While traditional switch statements are excellent for handling multiple discrete values, they can feel verbose when you simply want to map input values to output values. Modern C# introduces switch expressions – a more concise, functional programming approach that treats the entire switch construct as an expression that returns a value directly.
Switch expressions represent a paradigm shift from imperative "do this, then do that" thinking to functional "transform this input into that output" thinking. This approach reduces boilerplate code, eliminates common mistakes like forgotten break statements, and makes your intent clearer when performing value transformations.
Switch expressions are particularly powerful for mapping and transformation scenarios where you need to convert one set of values into another set of values. They excel at replacing lengthy if-else chains and verbose switch statements with clean, readable value mappings.
Understanding Switch Expression Syntax
Switch expressions use arrow syntax (=>) to create direct mappings between input values and output results. Unlike traditional switch statements that execute code blocks, switch expressions evaluate to a single value that can be assigned to a variable or used directly in other expressions.
The basic pattern follows this structure: examine an input value, match it against various patterns, and return the corresponding result for the first matching pattern. The underscore (_) serves as a catch-all pattern for any values not explicitly handled, ensuring that every possible input has a defined output.
// Basic switch expression syntax
var result = inputValue switch
{
pattern1 => result1,
pattern2 => result2,
_ => defaultResult
};
This syntax emphasizes the mapping relationship: "when the input matches pattern1, produce result1; when it matches pattern2, produce result2; otherwise, produce the default result." The entire construct is an expression that evaluates to a value, making it perfect for assignments and return statements.
Value Mapping with Switch Expressions
Switch expressions shine in scenarios where you need to transform discrete values. The most common use case involves mapping one set of values to another, such as converting status codes to user-friendly messages or translating enumerated values to display strings.
// Converting day numbers to names
int dayNumber = 3;
string dayName = dayNumber switch
{
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6 => "Saturday",
7 => "Sunday",
_ => "Invalid day"
};
Console.WriteLine($"Day {dayNumber} is {dayName}");
Compare this concise mapping to the equivalent traditional switch statement, which would require 15+ lines with repetitive case blocks and break statements. The switch expression version clearly communicates the mapping relationship without procedural clutter.
When using switch expressions for value mapping, organize your patterns logically – either alphabetically, numerically, or by frequency of use. This organization makes the mapping relationships clear and helps other developers understand your data transformations quickly.
Pattern Matching Beyond Equality
Modern switch expressions support sophisticated pattern matching that goes beyond simple value equality. Relational patterns allow you to match ranges using comparison operators, while logical patterns let you combine multiple conditions using `and`, `or`, and `not` keywords.
Range-based patterns are particularly useful for categorizing numeric data, such as converting test scores to letter grades or classifying data into performance tiers. The key insight is that patterns are evaluated in order, so you must arrange them from most specific to most general.
// Range-based pattern matching
int score = 87;
string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
>= 60 => "D",
_ => "F"
};
// Combining patterns with logical operators
char response = 'y';
bool confirmed = response switch
{
'Y' or 'y' => true,
'N' or 'n' => false,
_ => false // Default to false for safety
};
These patterns demonstrate how switch expressions can handle complex decision logic while maintaining readability. The `or` operator eliminates the need for duplicate case handling, while relational patterns provide intuitive ways to handle ranges and thresholds.
Compiler Optimizations and Safety
Switch expressions aren't just syntactic convenience – they enable important compiler optimizations and safety features. The compiler can analyze the complete set of patterns and generate efficient jump tables or decision trees, particularly when working with enums or small sets of constant values.
More importantly, switch expressions provide compile-time exhaustiveness checking in certain scenarios. When working with boolean values, enums, or other finite sets, the compiler can verify that you've handled all possible cases, reducing the likelihood of runtime errors. The required default case (underscore pattern) also ensures that unexpected values don't cause exceptions.
The requirement to handle all possible cases makes switch expressions more defensive than traditional switch statements. You cannot accidentally omit a case or forget a break statement – the compiler enforces completeness and correctness at compile time.
When to Choose Switch Expressions
Switch expressions work best for pure transformation scenarios where you're mapping inputs to outputs without side effects. They're ideal for configuration lookups, state transitions, category assignments, and any situation where the primary goal is value transformation rather than executing complex procedures.
Use traditional switch statements when you need to execute multiple statements per case, perform complex computations, or handle cases that require significantly different processing logic. Switch expressions excel when the focus is on the relationship between input and output values, not on the steps required to compute those relationships.
Consider switch expressions particularly valuable in functional programming scenarios where immutability and expression-oriented code improve maintainability. They work exceptionally well in LINQ queries, property initializers, and anywhere you need clean, declarative value transformations.
Switch expressions are part of C#'s evolution toward functional programming concepts. They reflect a broader industry trend of incorporating functional programming benefits – like immutability, expression-oriented code, and pattern matching – into traditionally object-oriented languages, making code more declarative and less error-prone.
Summary
Switch expressions represent modern C#'s approach to clean, expressive value mapping. They reduce boilerplate code, eliminate common switch statement pitfalls, and make transformation logic more readable and maintainable. By embracing the expression-oriented mindset, you can write more declarative code that clearly communicates its purpose.
The key benefits include improved readability through direct value mapping, enhanced safety through required exhaustiveness, and better performance through compiler optimizations. Use switch expressions when your primary need is transforming discrete input values into corresponding output values, especially when pattern matching or logical combinations add clarity to your decision logic.