Branch Control Flow

1. Basic if / if-else Branching

  1. The content inside if parentheses must be a boolean expression; implicit coercion to boolean values is not allowed.
  2. Multiple else if blocks are supported, with an optional final else block.
  3. Curly braces can be omitted for single-line logic, yet consistent use of braces is recommended to boost readability.
void main() {
  bool isRaining = false;
  bool isSnowing = true;

  if (isRaining) {
    print("Bring raincoat");
  } else if (isSnowing) {
    print("Wear thick coat");
  } else {
    print("Drive convertible");
  }
}Code language: Dart (dart)

Execution Output

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Wear thick coatCode language: CSS (css)

You can also use if alone

void main() {
  bool isRaining = false;
  bool isSnowing = true;

  if (isRaining) {
    print("Bring raincoat");
  }
}Code language: Dart (dart)

Or simply use if else

void main() {
  bool isRaining = false;
  bool isSnowing = true;

  if (isRaining) {
    print("Bring raincoat");
  } else {
    print("Drive convertible");
  }
}Code language: Dart (dart)

2. if-case Pattern Matching Branch (Dart 3.0+)

  1. Matches a pattern and destructures to bind variables accessible within the current scope upon successful match.
  2. Falls back to else when matching fails; when guards can be appended for extra boolean checks.
  3. Designed for single-value single-pattern matching; use switch statements for multi-pattern matching scenarios.
void main() {
  final pair = [100, 220];
  // Matches a two-element list holding two integers
  if (pair case [int x, int y]) {
    print("Coordinate: $x,$y");
  } else {
    throw FormatException("Invalid coordinate");
  }
}Code language: Dart (dart)

Execution Output

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Coordinate: 10,20Code language: CSS (css)

2: if-case with when Guard

void main() {
  final data = [8, 9];
  if (data case [int a, int b] when a > 5 && b > 5) {
    print("Both numbers are greater than 5");
  } else {
    print("Numbers do not meet criteria");
  }
}Code language: Dart (dart)

Execution Output

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Both numbers are greater than 5Code language: CSS (css)

3. switch Statements

Traditional procedural switch statement with no return value

  1. Cases support all pattern types: strings, constants, logical OR patterns, relational patterns
  2. Non-empty cases break automatically without manual break statements; empty cases trigger fallthrough by default
  3. Two methods for manual fallthrough: continue label or consecutive empty case blocks
  4. default block executes when no case matches; compatible with when guards
1: Basic String Matching
void main() {
  String command = "OPEN";
  switch (command) {
    case "CLOSED":
      print("Execute close logic");
    case "PENDING":
      print("Execute pending logic");
    case "OPEN":
      print("Execute open logic");
    default:
      print("Unknown command");
  }
}
Code language: Dart (dart)

Execution Output

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Execute open logicCode language: CSS (css)

2: Empty Case Fallthrough + continue Label Jump

String command = "OPEN";
switch (command) {
  case "OPEN":
    print("Open operation"); // ① Matches OPEN and prints message
    continue newCase; // ② Jumps straight to newCase marker, no backtracking

  case "DENIED": 
  case "CLOSED":
    print("Close operation");

  newCase: // ③ Target jump label
  case "PENDING":
    print("Unified pending handling logic"); // ④ Runs directly without checking command == "PENDING"
}Code language: Dart (dart)

Execution Output

D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Open operation
Unified pending handling logicCode language: CSS (css)

In this example, does continue newCase; jump to the newCase marker? But the subsequent case “PENDING” won’t match, so why does print("Unified pending handling logic"); still run?

Many readers will have this exact question

continue label; does not re-evaluate the matched value. Instead, it directly jumps to the entry point of the case marked by the label, skips all conditional checks, and executes code inside that branch immediately.

3: switch + when Guards

void main() {
  int score = 88;
  switch (score) {
    case int s when s >= 90:
      print("Excellent");
    case int s when s >= 60:
      print("Pass");
    default:
      print("Fail");
  }
}
Code language: Dart (dart)

Output: Pass

The code first verifies the input type must be integer. If type matches, assign value to variable s. After that, the when guard runs secondary validation. Code inside the case only executes when s satisfies the when condition. Note that even with two separate int s declarations, they exist within isolated scopes and do not conflict.

Each case int s creates an independent pattern binding with scope limited exclusively to its own case branch, with zero cross-branch interference.

You can use entirely different variable names for each case without altering functionality.

switch (score) {
  case int a when a >= 90:
    print("Excellent");
  case int b when b >= 60:
    print("Pass");
  default:
    print("Fail");
}Code language: Dart (dart)

4. switch Expressions

Syntax available starting Dart 3.0+, returns a value and frequently used for variable assignment

Differences from switch Statements

  1. No case keyword; patterns and return expressions separated via =>
  2. Every branch must evaluate to an expression, branches separated by commas
  3. No implicit fallthrough; all branches self-contained. Use the underscore wildcard _ as fallback instead of default when no patterns match
  4. Compatible with assignment, print calls, return statements and all other expression contexts

1: Basic Character Operator Matching (Logical OR Pattern)

void main() {
  const slash = 47, star = 42, comma = 44;
  int charCode = 42;

  final token = switch (charCode) {
    slash || star => "Operator",
    comma => "Punctuation",
    _ => "Invalid character"
  };
  print(token);
}
Code language: Dart (dart)

Execution Output

Operator

This sample defines constants storing ASCII values for three symbols. The charCode variable is checked against patterns to classify it as operator, punctuation or unrecognized symbol.

2: switch Expression + when Guard

void main() {
  int age = 22;
  String level = switch (age) {
    int a when a < 18 => "Minor",
    int a when a < 30 => "Young Adult",
    _ => "Adult"
  };
  print(level);
}Code language: Dart (dart)

Execution Output

Young Adult

3: Direct switch Expression Inside Function Return

void main() {
  print(getDesc(3));
}

String getDesc(int num) => switch (num) {
  1 => "One",
  2 => "Two",
  _ => "Other number"
};
Code language: Dart (dart)

Execution Output

Other number

Note: This switch construct is an expression, and getDesc is an arrow function — a distinctive Dart syntax absent from other C-style languages.

5. Exhaustiveness Checking

Triggers compile-time error when input values lack matching branches, forcing developers to cover all possible cases. Sealed classes and enums natively support exhaustiveness checks without requiring _ or default fallbacks.

1: Non-exhaustive Nullable Boolean Error (Comment out code and run to view error)

void main() {
  bool? nullableBool = null;
  // Uncommenting below code causes compile error: missing null match branch with no _/default fallback
  /*
  switch (nullableBool) {
    case true:
      print("True");
    case false:
      print("False");
  }
  */
  // Fix: Add null case or wildcard _ fallback
  switch (nullableBool) {
    case true:
      print("True");
    case false:
      print("False");
    case null:
      print("Null value");
  }
}Code language: PHP (php)

Execution Output

Null valueCode language: PHP (php)

2: Sealed Classes

Algebraic data type enforcing exhaustive pattern matching

import 'dart:math' as math;

// Sealed class: Subclasses may only be defined within this source file
sealed class Shape {}

// Subclass Square with side length parameter
class Square implements Shape {
  final double length;
  Square(this.length);
}

// Subclass Circle with radius parameter
class Circle implements Shape {
  final double radius;
  Circle(this.radius);
}

// Arrow function using switch expression to calculate area based on Shape subclass
double calculateArea(Shape shape) => switch (shape) {
  Square(length: var l) => l * l,
  Circle(radius: var r) => math.pi * r * r
  // Adding new Shape subclass triggers compile error alerting missing corresponding case
};

void main() {
  final Shape circle = Circle(5);
  print(calculateArea(circle));
  final Shape square = Square(4);
  print(calculateArea(square));
}
Code language: Dart (dart)

Execution Output

78.53981633974483
16.0Code language: CSS (css)

3: Exhaustive Matching with Enums

No need for underscore _ fallback wildcard

void main() {
  final Animal animal = Animal.cat;
  String name = switch (animal) {
    Animal.dog => "Dog",
    Animal.cat => "Cat"
  };
  print(name);
}

enum Animal { dog, cat }
Code language: Dart (dart)

Output: Cat

Enums contain a fixed finite set of values with no unexpected variants, eliminating requirement for fallback logic.

6. when Guards

Fully compatible with if-case, switch statements and switch expressions

Purpose of when: Runs additional boolean validation after successful pattern match. If guard evaluates false, execution proceeds to next branch without exiting the switch block.

1. if-case + when

void main() {
  List<int> arr = [10, 20];
  if (arr case [int x, int y] when x + y > 20) {
    print("Sum of two numbers exceeds 20");
  }
}Code language: Dart (dart)
Sum of two numbers exceeds 20

The code first validates the input matches a two-integer list pattern, then uses when to verify their combined value exceeds 20.

2. switch Statement + when

void main() {
  int num = 15;
  switch(num) {
    case int n when n % 2 == 0:
      print("Even number");
    case int n when n % 2 != 0:
      print("Odd number");
  }
}
Code language: PHP (php)

Output: Odd number

Checks integer type first, then executes the when guard condition.

3. switch Expression + when

void main() {
  int num = 15;
  String res = switch(num) {
    int n when n % 2 == 0 => "Even number",
    _ => "Odd number"
  };
  print(res);
}
Code language: PHP (php)

Leave a Reply

Your email address will not be published. Required fields are marked *