C# switch expression
last modified January 19, 2024
In this article we show how to use switch expressions in C#.
Switch expressions are a powerful enhancement for the classic switch statements. They consists of arms each of which returns a value.
The arms may evaluate the following:
- values
- types
- relational logic
- when guards
- properties
- tuples
- lists
C# switch expression value pattern
With a value pattern, the switch arms are based on constant values such as integers or strings.
Console.Write("Enter a domain name: "); string? domain = Console.ReadLine(); domain = domain?.Trim().ToLower(); string result = domain switch { "us" => "United States", "de" => "Germany", "sk" => "Slovakia", "hu" => "Hungary", _ => "Unknown" }; Console.WriteLine(result);
In the example, we use a switch expression to map a country name to its domain name.
$ dotnet run Enter a domain name: sk Slovakia # dotnet run Enter a domain name: jp Unknown
C# switch expression type pattern
Data types can be patterns to the switch expression.
int age = 23; string name = "Peter"; List<string> colors = ["blue", "khaki", "orange"]; int[] nums = [1, 2, 3, 4, 5]; Console.WriteLine(check(age)); Console.WriteLine(check(name)); Console.WriteLine(check(colors)); Console.WriteLine(check(nums)); object check(object val) => val switch { int => "integer", string => "string", List<string> => "list of strings", Array => "array", _ => "unknown" };
In the example, we find out the data type of a variable using switch expression.
$ dotnet run integer string list of strings array
C# switch expression relational pattern
Powerful logic can be constructed with relational patterns.
List<int> nums = [-3, 2, 0, 1, 9, -2, 7]; foreach (var num in nums) { var res = num switch { < 0 => "negative", 0 => "zero", > 0 => "positive" }; Console.WriteLine($"{num} is {res}"); }
We have a list of integers. In a foreach loop, we go through the list and print whether the value is negative, positive, or zero with a switch expression. Inside the switch expression, we use simple relational expressions.
$ dotnet run -3 is negative 2 is positive 0 is zero 1 is positive 9 is positive -2 is negative 7 is positive
C# switch expression when guards
Using when guards adds some additional flexibility to our expression arms.
List<User> users = [ new ("John", "Doe", 34), new ("Roger", "Roe", 44), new ("Jane", "Doe", 44), new ("Robert", "Molnar", 41), new ("Lucia", "Petrovicova", 16), ]; foreach (var user in users) { Console.WriteLine(checkPerson(user)); } string checkPerson(User u) { return u switch { { LastName: "Doe" } => "Doe family", { Age: var age } when age < 18 => "minor person", _ => $"{u}" }; } record User(string FirstName, string LastName, int Age);
In the example, we use a when guard to account for users younger than 18.
$ dotnet run Doe family User { FirstName = Roger, LastName = Roe, Age = 44 } Doe family User { FirstName = Robert, LastName = Molnar, Age = 41 } minor person
C# switch expression logical pattern
The and
and or
operators can be used in switch
expressions.
List<User> users = [ new ("Peter Novak", "driver", new DateTime(2000, 12, 1)), new ("John Doe", "gardener", new DateTime(1996, 2, 10)), new ("Roger Roe", "teacher", new DateTime(1976, 5, 9)), new ("Lucia Smith", "student", new DateTime(2007, 8, 18)), new ("Roman Green", "retired", new DateTime(1945, 7, 21)), ]; foreach (var user in users) { int age = GetAge(user); string res = age switch { > 65 => "senior", >= 18 and <= 64 => "adult", < 18 => "minor", _ => "unknown", }; Console.WriteLine($"{user.Name} is {res}"); } int GetAge(User user) { return (int)Math.Floor((DateTime.Now - user.Dob).TotalDays / 365.25D); } record User(string Name, string Occupation, DateTime Dob);
Logical and
operator is used to assign the adult string to users
with age range between 18 and 65.
$ dotnet run Peter Novak is adult John Doe is adult Roger Roe is adult Lucia Smith is minor Roman Green is senior
In the following example, we have an or
expression.
var q = @" WWI started in: 1) 1912 2) 1914 3) 1918 "; Console.WriteLine(q); var inp = Console.ReadLine(); var ans = int.Parse(inp.Trim()); var res = ans switch { 1 or 3 => "Incorrect", 2 => "correct", _ => "unknown option" }; Console.WriteLine(res);
The example examines the input from a user and uses an or
expression in the switch expression.
C# switch expression property pattern
The values of object properties can be patterns in a switch expression.
List<Product> products = [ new ("Product A", 70m, 1, 10), new ("Product B", 50m, 3, 15), new ("Product C", 35m, 2, 20) ]; foreach (var product in products) { decimal sum = product switch { Product { Quantity: 2 } => product.Price * product.Quantity * (1 - product.Discount / 100m), _ => product.Price * product.Quantity, }; Console.WriteLine($"The final sum for {product.Name} is {sum}"); } record Product(string Name, decimal Price, int Quantity, int Discount);
In the example, we apply a discount to the price of a product if we have bought two items of the product.
$ dotnet run The final sum for Product A is 70 The final sum for Product B is 150 The final sum for Product C is 56.0
Twenty percent discount was applied to Product C.
C# switch expression tuple pattern
Tuple pattern can be used by switch expressions.
while (true) { var menu = "Select: \n1 -> rock\n2 -> paper\n3 -> scissors\n4 -> finish"; Console.WriteLine(menu); string[] options = {"rock", "paper", "scissors"}; int val; try { var line = Console.ReadLine(); if (string.IsNullOrEmpty(line)) { Console.WriteLine("Invalid choice"); continue; } val = int.Parse(line); } catch (FormatException) { Console.WriteLine("Invalid choice"); continue; } if (val == 4) { break; } if (val < 1 || val > 4) { Console.WriteLine("Invalid choice"); continue; } string human = options[val-1]; var rnd = new Random(); int n = rnd.Next(0, 3); string computer = options[n]; Console.WriteLine($"I have {computer}, you have {human}"); var res = RockPaperScissors(human, computer); Console.WriteLine(res); } Console.WriteLine("game finished"); string RockPaperScissors(string human, string computer) => (human, computer) switch { ("rock", "paper") => "Rock is covered by paper. You loose", ("rock", "scissors") => "Rock breaks scissors. You win.", ("paper", "rock") => "Paper covers rock. You win.", ("paper", "scissors") => "Paper is cut by scissors. You loose.", ("scissors", "rock") => "Scissors are broken by rock. You loose.", ("scissors", "paper") => "Scissors cut paper. You win.", (_, _) => "tie" };
We have a Rock paper scissors game in which we utilize the tuple expression.
string RockPaperScissors(string human, string computer) => (human, computer) switch { ("rock", "paper") => "Rock is covered by paper. You loose", ("rock", "scissors") => "Rock breaks scissors. You win.", ...
From the human and computer choices we form tuples which are used as patterns in the switch expression to reach the game conclusion.
$ dotnet run Select: 1 -> rock 2 -> paper 3 -> scissors 4 -> finish 1 I have rock, you have rock tie Select: 1 -> rock 2 -> paper 3 -> scissors 4 -> finish 2 I have paper, you have paper tie Select: 1 -> rock 2 -> paper 3 -> scissors 4 -> finish 3 I have paper, you have scissors Scissors cut paper. You win. Select: 1 -> rock 2 -> paper 3 -> scissors 4 -> finish 4 game finished
List patterns
Since C# 11, switch expression arms can evaluate list patterns.
List<Student> students = [ new ("John", ['a', 'b', 'a', 'c', 'd', 'd', 'e']), new ("Lucia", ['b', 'b', 'c', 'c', 'a', 'e', 'e']), new ("Paul", ['a', 'b', 'a', 'c', 'b', 'e', 'e']), new ("Roger", ['a', 'c', 'c', 'c', 'a', 'b', 'e']), new ("Michal", ['b', 'b', 'c', 'c', 'a', 'e', 'e']), ]; foreach (var student in students) { string res = student.Answers switch { ['b', 'b', 'c', 'c', 'a', 'e', 'e'] => $"{student.Name} has passed", _ => $"{student.Name} has failed" }; Console.WriteLine(res); } record Student(string Name, List<char> Answers);
Students are having a test with seven questions. The questions have answers 'a' through 'e'. To pass a test, all questions must be answered correctly.
List<Student> students = [ new ("John", ['a', 'b', 'a', 'c', 'd', 'd', 'e']), new ("Lucia", ['b', 'b', 'c', 'c', 'a', 'e', 'e']), new ("Paul", ['a', 'b', 'a', 'c', 'b', 'e', 'e']), new ("Roger", ['a', 'c', 'c', 'c', 'a', 'b', 'e']), new ("Michal", ['b', 'b', 'c', 'c', 'a', 'e', 'e']), ];
This is a list of students and their test answers.
string res = student.Answers switch { ['b', 'b', 'c', 'c', 'a', 'e', 'e'] => $"{student.Name} has passed", _ => $"{student.Name} has failed" };
We check results against the correct one. The pattern is a list of characters that represent correct answers.
$ dotnet run John has failed Lucia has passed Paul has failed Roger has failed Michal has passed
Source
switch expression - pattern matching expressions using the switch keyword
In this article we have presented C# switch expression.
Author
List all C# tutorials.