What is Pattern Matching?
Pattern matching (Dart 3.0+) lets you match a value against a shape or structure and extract parts of it in one expression. Dart patterns work in switch statements and expressions, variable declarations, and for-loop variables.
Switch Expressions
// Switch expression (returns a value)
String describe(Object value) => switch (value) {
int n when n < 0 => 'negative int',
int n when n == 0 => 'zero',
int _ => 'positive int',
double _ => 'a double',
String s => 'a string: "$s"',
List l => 'a list of $${l.length} items',
_ => 'unknown',
};
void main() {
print(describe(-5)); // negative int
print(describe(0)); // zero
print(describe(42)); // positive int
print(describe(3.14)); // a double
print(describe('hello')); // a string: "hello"
print(describe([1,2,3])); // a list of 3 items
}
Record Patterns
String describePoint((int, int) point) => switch (point) {
(0, 0) => 'Origin',
(int x, 0) => 'On x-axis at $x',
(0, int y) => 'On y-axis at $y',
(int x, int y) when x == y => 'On diagonal at ($x, $y)',
(int x, int y) => 'Point at ($x, $y)',
};
void main() {
print(describePoint((0, 0))); // Origin
print(describePoint((5, 0))); // On x-axis at 5
print(describePoint((3, 3))); // On diagonal at (3, 3)
print(describePoint((2, 7))); // Point at (2, 7)
}
List Patterns
String describeList(List<int> list) => switch (list) {
[] => 'empty',
[var x] => 'single: $x',
[var x, var y] => 'pair: $x, $y',
[var first, ..., var last] => 'starts $first, ends $last',
};
print(describeList([])); // empty
print(describeList([42])); // single: 42
print(describeList([1, 2])); // pair: 1, 2
print(describeList([1,2,3,4,5]));// starts 1, ends 5
Guard Clauses
// 'when' adds a boolean guard condition
String classify(int n) => switch (n) {
0 => 'zero',
int x when x < 0 => 'negative',
int x when x % 2 == 0 => 'positive even',
_ => 'positive odd',
};
Practical Example
sealed class Shape {}
class Circle extends Shape { final double radius; Circle(this.radius); }
class Rectangle extends Shape { final double w, h; Rectangle(this.w, this.h); }
class Triangle extends Shape { final double b, height; Triangle(this.b, this.height); }
double area(Shape shape) => switch (shape) {
Circle(radius: var r) => 3.14159 * r * r,
Rectangle(w: var w, h: var h) => w * h,
Triangle(b: var b, height: var h) => 0.5 * b * h,
};
void main() {
print(area(Circle(5)).toStringAsFixed(2)); // 78.54
print(area(Rectangle(4, 6)).toStringAsFixed(2)); // 24.00
print(area(Triangle(3, 8)).toStringAsFixed(2)); // 12.00
}
🧠 Quiz
1. What is a switch expression in Dart?
- A) A switch statement with expressions inside
- B) A switch that returns a value ✅
- C) A switch for matching expressions only
- D) A Dart 2 feature
2. What does the when keyword add to a pattern case?
- A) A type check
- B) A boolean guard condition ✅
- C) An optional field
- D) A loop
Summary
Dart 3.0 pattern matching enables switch expressions that return values, record/list patterns for structural matching, and when guards for conditional cases. Use sealed classes with pattern matching for exhaustive type checking. Patterns can appear in switch, variable declarations, and for loops.