C# 12 introduces several improvements to switch expressions, making them more powerful and concise. Here are some of the key improvements.
Enhanced Switch Expressions
Expression Syntax: Switch expressions now use a more concise syntax, allowing you to return a value directly from each case. This eliminates the need for break statements and makes the code more readable.
Pattern Matching: C# 12 expands on pattern matching, introduced in C# 7, allowing for more complex and expressive patterns. You can now match against types, properties, and even deconstruct objects.
Let Pattern: The let pattern allows you to introduce intermediate variables within a pattern match. This is useful for simplifying complex conditions and reusing intermediate results.
Recursive Patterns: C# 12 supports recursive patterns, which enable matching and deconstructing nested objects. This is particularly useful for working with complex data structures.
Here's an example demonstrating some of these features.
using System;
public class Employee
{
public string Name { get; set; }
public int Age { get; set; }
}
class Program
{
static void Main()
{
var employee = new Employee { Name = "Alice", Age = 30 };
string result = employee switch
{
{ Name: "Alice", Age: 30 } => "Alice is 30 years old.",
{ Name: "Bob", Age: _ } => "Bob's age is unknown.",
{ Age: var age } when age > 18 => $"Employee is older than 18: {age}.",
_ => "Unknown person."
};
Console.WriteLine(result);
}
}
Expression Syntax: The switch expression directly returns a value for each case.
Pattern Matching: The cases use patterns to match against the properties of the Person object.
Let Pattern: The var age introduces an intermediate variable within the pattern.
Recursive Patterns: Not demonstrated in this example, but you can use recursive patterns to match nested objects.
These enhancements make switch expressions in C# 12 more powerful, expressive, and easier to read.
List Pattern:
C# 12 introduces the list pattern, allowing you to match lists or arrays based on their elements. This is useful for matching sequences of values directly within the switch expression.
var numbers = new[] { 1, 2, 3, 4, 6, 7 };
string result = numbers switch
{
[1, 2, 3] => "Matched exact sequence: 1, 2, 3",
[_, 2, _] => "Matched any element in the first and last position with 2 in the middle",
[1, ..] => "Starts with 1",
_ => "No match"
};
Console.WriteLine(result);
Relational Patterns:
Relational patterns enable you to match values based on relational operators. This expands the expressive power of switch expressions, allowing more complex conditions.
int score = 85;
string grade = score switch
{
>= 90 => "A",
>= 80 => "B",
>= 70 => "C",
>= 60 => "D",
_ => "F"
};
Console.WriteLine($"Score: {score}, Grade: {grade}");
Type Patterns:
Type patterns allow you to match and cast a value based on its type within the switch expression. This is particularly useful for working with objects of different types.
object value = "Hello";
string message = value switch
{
int i => $"It's an integer: {i}",
string s => $"It's a string: {s}",
_ => "Unknown type"
};
Console.WriteLine(message);
Combinatorial Patterns:
Combine multiple patterns using logical operators like and, or, and not to create complex matching conditions.
var employee = new Employee { Name = "Alice", Age = 30 };
string description = employee switch
{
{ Name: "Alice", Age: > 25 and < 35 } => "Alice in her late twenties to early thirties",
{ Name: "Bob" or "Charlie", Age: _ } => "Bob or Charlie",
{ Age: not < 18 } => "An adult",
_ => "No match"
};
Console.WriteLine(description);
These improvements in C# 12 make switch expressions more powerful and versatile, enhancing your ability to write clear and concise code.