Control Flow: If, Else & Switch
What Is Control Flow?
By default, Dart executes code from top to bottom, one line after another. Control flow statements let you change this behavior -- you can make decisions, skip blocks of code, or choose between different paths based on conditions. Without control flow, every program would do the exact same thing every time it runs.
The if Statement
The if statement is the most basic decision-making tool. It executes a block of code only when a condition evaluates to true.
Basic if Statement
void main() {
int temperature = 35;
if (temperature > 30) {
print('It is hot outside!');
}
// With a single statement, braces are optional (but recommended)
if (temperature > 30) print('Stay hydrated!');
// The condition MUST be a bool -- Dart is strict
// if (1) { ... } // ERROR! 1 is not a bool
// if ('hello') { ... } // ERROR! String is not a bool
}
{} even for single-line if statements. It prevents bugs when you later add more lines and makes the code easier to read.The if-else Statement
When you want to do one thing if a condition is true and something else if it is false, use if-else:
if-else
void main() {
int age = 16;
if (age >= 18) {
print('You can vote.');
} else {
print('You cannot vote yet.');
}
// Output: You cannot vote yet.
// Another example
double balance = 150.0;
double price = 200.0;
if (balance >= price) {
print('Purchase successful!');
balance -= price;
} else {
print('Insufficient funds. You need \$${(price - balance).toStringAsFixed(2)} more.');
}
// Output: Insufficient funds. You need \$50.00 more.
}
The if-else if-else Chain
When you have multiple conditions to check, chain them with else if. Dart evaluates each condition from top to bottom and executes the first block whose condition is true. If none match, the else block runs.
Multiple Conditions
void main() {
int score = 78;
String grade;
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else if (score >= 70) {
grade = 'C';
} else if (score >= 60) {
grade = 'D';
} else {
grade = 'F';
}
print('Score: \$score, Grade: \$grade');
// Output: Score: 78, Grade: C
}
true condition. If you put score >= 60 before score >= 90, a score of 95 would get a “D” instead of an “A” because 95 >= 60 is true and would match first.Nested if Statements
You can place if statements inside other if statements. This is useful when a second decision depends on the first.
Nested Conditions
void main() {
bool isLoggedIn = true;
String role = 'admin';
if (isLoggedIn) {
if (role == 'admin') {
print('Welcome, Admin! You have full access.');
} else if (role == 'editor') {
print('Welcome, Editor! You can edit content.');
} else {
print('Welcome! You have read-only access.');
}
} else {
print('Please log in first.');
}
}
if (isLoggedIn && role == 'admin') is often cleaner than two nested ifs.Combining Conditions
Use logical operators (&&, ||, !) to combine multiple conditions in a single if statement:
Complex Conditions
void main() {
int age = 25;
bool hasLicense = true;
bool hasInsurance = true;
// AND -- all conditions must be true
if (age >= 18 && hasLicense && hasInsurance) {
print('You can drive legally.');
}
// OR -- at least one must be true
String day = 'Saturday';
if (day == 'Saturday' || day == 'Sunday') {
print('It is the weekend!');
}
// NOT -- invert a condition
bool isBanned = false;
if (!isBanned) {
print('Welcome to the platform.');
}
// Mixed operators with parentheses for clarity
int score = 75;
bool isVIP = true;
if ((score >= 80) || (score >= 70 && isVIP)) {
print('Access granted.');
}
}
The Ternary Operator (Conditional Expression)
For simple if-else assignments, the ternary operator provides a compact one-line alternative:
Ternary vs if-else
void main() {
int temperature = 25;
// Using if-else (verbose)
String weather;
if (temperature > 30) {
weather = 'Hot';
} else {
weather = 'Pleasant';
}
// Using ternary (concise)
String weather2 = temperature > 30 ? 'Hot' : 'Pleasant';
print(weather2); // Pleasant
// Useful inside string interpolation
int items = 3;
print('You have \$items item${items == 1 ? "" : "s"} in your cart.');
// Output: You have 3 items in your cart.
}
The switch Statement
When you need to compare one value against many possible matches, switch is cleaner than a long chain of if-else if. Each case represents one possible value.
Basic switch Statement
void main() {
String day = 'Wednesday';
switch (day) {
case 'Monday':
print('Start of the work week.');
break;
case 'Tuesday':
case 'Wednesday':
case 'Thursday':
print('Midweek hustle.');
break;
case 'Friday':
print('Almost weekend!');
break;
case 'Saturday':
case 'Sunday':
print('Weekend vibes!');
break;
default:
print('Invalid day.');
}
// Output: Midweek hustle.
}
case must end with break, return, continue, or throw. Unlike C or JavaScript, Dart does not allow implicit fall-through. However, empty cases (like Tuesday and Wednesday above) naturally fall through to the next non-empty case.Switch with Different Types
Switch on Integers and Enums
void main() {
// Switch on int
int statusCode = 404;
switch (statusCode) {
case 200:
print('OK - Request successful');
break;
case 301:
print('Moved Permanently');
break;
case 404:
print('Not Found');
break;
case 500:
print('Internal Server Error');
break;
default:
print('Unknown status code: \$statusCode');
}
// Output: Not Found
}
Switch Expressions (Dart 3+)
Dart 3 introduced switch expressions, which let you use switch as a value-returning expression. This is more concise and eliminates the need for break statements.
Switch Expression Syntax
void main() {
String day = 'Friday';
// Switch expression -- returns a value
String type = switch (day) {
'Monday' || 'Tuesday' || 'Wednesday' || 'Thursday' => 'Weekday',
'Friday' => 'Almost Weekend',
'Saturday' || 'Sunday' => 'Weekend',
_ => 'Invalid day', // _ is the default/wildcard
};
print(type); // Almost Weekend
}
Switch Expression with Numbers
void main() {
int statusCode = 200;
String message = switch (statusCode) {
200 => 'Success',
301 => 'Redirected',
404 => 'Not Found',
500 => 'Server Error',
_ => 'Unknown (\$statusCode)',
};
print(message); // Success
}
Pattern Matching in Switch (Dart 3+)
Dart 3 also brings powerful pattern matching to switch statements, allowing you to match on types, conditions, and even destructure values.
Pattern Matching Basics
void main() {
// Type pattern matching
dynamic value = 42;
String description = switch (value) {
int n when n > 0 => 'Positive integer: \$n',
int n when n < 0 => 'Negative integer: \$n',
int() => 'Zero',
double d => 'Double: \$d',
String s => 'String: \$s',
_ => 'Something else',
};
print(description); // Positive integer: 42
}
Guard Clauses with when
void main() {
int age = 25;
String category = switch (age) {
< 0 => 'Invalid age',
< 13 => 'Child',
< 18 => 'Teenager',
< 60 => 'Adult',
< 100 => 'Senior',
_ => 'Invalid age',
};
print('Age \$age: \$category'); // Age 25: Adult
}
if-case Statements (Dart 3+)
Dart 3 also allows pattern matching directly inside if statements using if-case:
if-case Pattern Matching
void main() {
// Check type and bind variable in one step
dynamic data = 'Hello, Dart!';
if (data case String text) {
print('Got a string: \$text (length: ${text.length})');
}
// With guard clause
int value = 42;
if (value case int n when n > 0 && n < 100) {
print('\$n is between 1 and 99');
}
// Matching list patterns
var list = [1, 2, 3];
if (list case [int first, int second, int third]) {
print('Three elements: \$first, \$second, \$third');
}
}
Practical Examples
Example: Simple Login Validator
void main() {
String username = 'admin';
String password = 'secret123';
if (username.isEmpty || password.isEmpty) {
print('Error: Please fill in all fields.');
} else if (username.length < 3) {
print('Error: Username must be at least 3 characters.');
} else if (password.length < 8) {
print('Error: Password must be at least 8 characters.');
} else if (username == 'admin' && password == 'secret123') {
print('Login successful! Welcome, \$username.');
} else {
print('Error: Invalid username or password.');
}
}
Example: Calculator with Switch Expression
void main() {
double a = 10;
double b = 3;
String operator = '/';
String result = switch (operator) {
'+' => '\$a + \$b = ${a + b}',
'-' => '\$a - \$b = ${a - b}',
'*' => '\$a * \$b = ${a * b}',
'/' when b != 0 => '\$a / \$b = ${(a / b).toStringAsFixed(2)}',
'/' => 'Error: Division by zero',
_ => 'Error: Unknown operator \$operator',
};
print(result); // 10.0 / 3.0 = 3.33
}
Practice Exercise
Open DartPad and create a program that: (1) Uses an if-else if chain to determine a student’s letter grade and feedback message based on their score (A: Excellent, B: Good, C: Average, D: Below Average, F: Failing). (2) Uses a switch expression to convert a month number (1-12) to its name. (3) Uses combined conditions with && and || to check if a person qualifies for a discount (either a student OR age over 60 AND a member). (4) Uses an if-case statement to check if a dynamic value is a positive integer.