Switch statement has changed quite a lot since the early versions of the language. I can't keep track of the changes.
Today, you can use switch to match not only values, but also types, properties, collections, and more.
Let's look at how we got here.
1. The original switch
The switch statement has been part of C# since C# 1.0.
Originally, its job was quite straightforward: take a value and execute a block of code depending on which constant it matches.
Imagine an application processing an order status:
Role status = Role.User;
switch (status)
{
case Role.Admin:
// Execute logic...
break;
case Role.Editor:
// Execute logic...
break;
case Role.Viewer:
// Execute logic...
break;
default:
// Execute logic...
break;
}Each case represented a value.
It was useful, but fairly limited.
You couldn't say:
If the number is greater than 100.
or:
If this object is a Customer.
The cases were primarily about matching known values.
There was also a familiar break at the end of each case.
2. string made switch more practical
As C# evolved, switch became useful with more types, including string.
For example:
string role = "Admin";
switch (role)
{
case "Admin":
// Execute logic...
break;
case "Editor":
// Execute logic...
break;
case "Viewer":
// Execute logic...
break;
default:
// Execute logic...
break;
}This is probably the version of switch many developers first encountered.
But eventually developers wanted to express something more complicated than:
Does this value equal X?They wanted to ask:
What type is this?
Does this object have these properties?
Does this collection have this shape?
That's where pattern matching changed the story.
3. C# 7: switch starts understanding patterns
This was one of the biggest changes in the history of switch.
Instead of only asking:
Does this value equal this constant?
you could start asking:
Does this value have this type?
For example:
object value = "Hello";
switch (value)
{
case string text:
// Execute logic...
break;
case int number:
// Execute logic...
break;
case DateTime date:
// Execute logic...
break;
default:
// Execute logic...
break;
}Notice what happened here.
We're not comparing:
value == "Hello"We're asking what value actually is.
This was a major shift in how developers could think about switch.
4. When allowed additional conditions
Pattern matching became even more useful when C# allowed conditions with when.
For example, suppose we receive different kinds of messages:
object message = 150;
switch (message)
{
case int number when number > 100:
// Execute logic...
break;
case int number:
// Execute logic...
break;
default:
// Execute logic...
break;
}Now switch isn't simply checking whether the value is an int.
It's checking:
Is it an int?
Is it greater than 100?
yes -> Large numberThe when clause adds another condition to the pattern. Modern C# still supports this approach.
5. C# 8: the switch expression
Then came another major change: the switch expression.
This is probably the change that made modern switch look completely different from the old version.
Previously, if we wanted to convert an order status into a message, we might write:
string GetMessage(Role role)
{
switch (role)
{
case Role.Viewer:
return // Execute logic...
case Role.Admin:
return // Execute logic...
case Role.Editor:
return // Execute logic...
default:
return // Execute logic...
}
}C# 8 introduced a much more concise way of expressing the same idea:
string GetMessage(Role role)
{
return role switch
{
Role.Editor=> "Is Editor",
Role.Admin => "Is Admin",
Role.Viewer => "Is Viewer",
_ => "Is User"
};
}This is called a switch expression because it produces a value.
6. C# 9: relational and logical patterns
We are not done yet, the evolution didn't stop there.
C# 9 introduced relational patterns such as:
< 18
>= 18
> 100
<= 500
and logical patterns such as:
and
or
not
7. Property patterns
Now things get more interesting.
Suppose we have:
public class Customer
{
public string Country { get; set; }
public int Age { get; set; }
}We can use a switch to inspect the object's properties.
string GetCustomerCategory(Customer customer) =>
customer switch
{
{ Country: "Tunisia", Age: >= 18 } => "Adult customer from Tunisia",
{ Country: "France", Age: >= 18 } => "Adult customer from France",
{ Age: < 18 } => "Minor",
_ => "Other"
};Notice that we're no longer switching on a single value.
We're matching the shape and properties of an object.
This is called a property pattern.
8. C# 11: list patterns
Another interesting addition was list patterns.
You can now match the structure of an array or collection.
For example:
string Describe(int[] values) =>
values switch
{
[] => "Empty",
[1, 2, 3] => "Exactly 1, 2, 3",
[1, ..] => "Starts with 1",
[.., 5] => "Ends with 5",
_ => "Something else"
};9. switch statement vs switch expression
This is something I think is worth making clear because the terminology can be confusing.
They're related, but they're not the same thing.
A switch statement:
switch (status)
{
case OrderStatus.Paid:
SendEmail();
UpdateDatabase();
break;
case OrderStatus.Cancelled:
Refund();
break;
}is useful when each branch needs to execute one or more operations.
A switch expression:
var message = status switch
{
OrderStatus.Paid => "Payment received",
OrderStatus.Cancelled => "Order cancelled",
_ => "Unknown"
};is useful when the main purpose is to calculate a value.

Sam HobbsPosted Sep 2, 2026, 5:35 PM
The history of the switch statement begins with ALGOL 58 and Fortran in about 1958. They used the term switch but it was quite different from later versions. Algol in the 1960s had a more structured multi-way selection construct. BCPL was a predecessor of the C language and had a switchon statement much like C. The switch statement in the first version of C# was based on the switch statement in C. Yes the switch statement in the first version of C# was limited compared to what C has; partially for safety and partially due to limitations of the Common Intermediate Language (CIL). I think that an explanation of why those limitations existed would be interesting. An explanation of why a break is required for every case and what the advantage of the C way of doing it is useful would be interesting.