Match: Switch on Steroids
- Chris Woodruff
- April 27, 2025
- Rust
- .NET, C#, dotnet, programming, rust
- 0 Comments
Welcome to Day 17! By now, we’ve covered some seriously cool Rust features, but today might be my favorite so far: the match expression. If you’re coming from a C# background—especially with the newer C# 8+ switch expressions—you might think you’ve seen it all. Trust me, Rust’s match is like a switch statement on steroids, protein shakes, and a Red Bull chaser.
Basic Match: Rust’s Superpowered Switch
In Rust, match is incredibly powerful and expressive. At its core, it’s used to match a value against multiple patterns. Think of it like a Swiss Army knife—it can handle anything from simple cases to complex scenarios with ease:
fn main() {
let number = 4;
match number {
1 => println!("One!"),
2 | 3 | 5 | 7 => println!("Prime"),
4..=10 => println!("Between 4 and 10"),
_ => println!("Something else"),
}
}
Cool, right? Rust lets you handle multiple values (2 | 3 | 5 | 7) and even ranges (4..=10) with clean, concise syntax.
Pattern Matching vs. C# Switch Expressions
C# devs might recognize pattern matching from recent language updates. Let’s quickly remind ourselves of what C# 8+ switch expressions look like:
var number = 4;
var result = number switch
{
1 => "One",
2 or 3 or 5 or 7 => "Prime",
>= 4 and <= 10 => "Between 4 and 10",
_ => "Something else"
};
Console.WriteLine(result);
Both languages share similarities, but Rust’s match goes even further:
- Exhaustive Checks: Rust enforces exhaustive pattern matching at compile-time. If you miss a case, Rust won’t compile until you handle every possible scenario.
- Powerful Patterns: Rust can match complex data types, destructure tuples and structs, and even match on enum variants.
Advanced Match: Pattern Matching on Complex Types
Here’s where Rust really flexes its muscles:
enum Coin {
Penny,
Nickel,
Dime,
Quarter(UsState),
}
enum UsState {
Alabama,
Alaska,
// more states...
}
fn value_in_cents(coin: Coin) -> u8 {
match coin {
Coin::Penny => 1,
Coin::Nickel => 5,
Coin::Dime => 10,
Coin::Quarter(state) => {
println!("State quarter from {:?}!", state);
25
},
}
}
fn main() {
let coin = Coin::Quarter(UsState::Alaska);
println!("Value: {} cents", value_in_cents(coin));
}
This example demonstrates how match elegantly destructures and matches data within enums—something C# is starting to do but not yet as fluidly.
The Wildcard _ to the Rescue
One more powerful feature: Rust’s wildcard _. This ensures every case is covered without explicitly defining them all:
let some_number = Some(5);
match some_number {
Some(7) => println!("Lucky number 7!"),
_ => println!("Some other number"),
}
Why Rust’s Match Is a Game-Changer
- Safety: You simply cannot miss a case by accident. Rust forces you to handle every scenario explicitly or use a wildcard.
- Readability: Complex logic stays concise and clear.
- Maintainability: Adding or modifying patterns is straightforward, making your code easy to evolve and understand.
Wrap-Up
Rust’s match isn’t just powerful—it’s addictive. Once you start using it, you’ll wonder how you ever managed complex branching logic without it. It’s more than just a switch statement; it’s pattern matching at its very best.
Tomorrow, we’ll push pattern matching even further with destructuring—prepare for another thrilling Rust adventure!

