Dart Control Flow
Control flow determines the order in which code in a program executes.
This chapter introduces conditional judgments (if/else, switch) and loop statements (for, while) in Dart, as well as the use of break and continue.
if / else / else if Conditional Statements
The if statement is the most basic control flow structure; it decides whether to execute a piece of code based on a condition.
Example
Basic if statements:
int score = 85;
// Basic if: executes when condition is true
if (score >= 60) {
print(EXAMPLE, congratulations, you passed!);
}
// if-else: choose one of two
if (score >= 90) {
print('Excellent');
} else {
print(Keep it up!);
}
// if-else if-else: multi-branch selection
if (score >= 90) {
print(Grade: A);
} else if (score >= 80) {
print(Grade: B);
} else if (score >= 70) {
print(Grade: C);
} else if (score >= 60) {
print(Grade: D);
} else {
print(Grade: F (fail));
}
}
EXAMPLE 恭喜,你及格了! 继续加油 等级:B
In Dart, conditional expressions must be of type bool. You cannot use 0, '', null, etc. as conditions like in JavaScript—these will directly cause compilation errors in Dart.
Nested if statements
if statements can be nested inside each other to handle more complex logic.
Example
bool isLoggedIn = true;
bool isAdmin = false;
String username = 'example';
if (isLoggedIn) {
// Outer check: whether logged in
if (isAdmin) {
// Inner check: whether admin
print(Welcome back, admin $username);
} else {
print(Welcome back, $username);
}
} else {
print(Please log in first);
}
}
欢迎回来,example
Too many nesting levels can reduce readability; it is recommended not to exceed 3 levels.
If the logic is truly complex, consider using early returns or splitting functions to simplify.
Example
Replacing deep nesting with early returns:
String getAccessMessage(bool isLoggedIn, bool isAdmin, String name) {
// First handle the 'return if condition not met' case
if (!isLoggedIn) {
return Please log in first;
}
if (!isAdmin) {
return 'You do not have admin permissions';
}
// Finally, the main logic
return 'Welcome back, admin $name';
}
void main() {
print(getAccessMessage(true, false, 'example'));
print(getAccessMessage(true, true, 'example'));
}
你没有管理权限 欢迎回来,管理员 example
switch / case multi-branch selection
When a variable has multiple fixed possible values, switch is clearer than if-else if.
Example
String day = 'Wednesday';
switch (day) {
case 'Monday':
print('A new week has started');
break; // break ends the current case, preventing 'fall-through' to the next case
case 'Tuesday':
print('The second day of hard work');
break;
case 'Wednesday':
print('Halfway through the week');
break;
case 'Thursday':
print('Almost Friday');
break;
case 'Friday':
print('TGIF!');
break;
case 'Saturday':
case 'Sunday':
// Multiple cases can share one block of code
print('Happy weekend!');
break;
default:
// Runs when no case matches
print('Unknown date');
}
}
The week is half over.
Dart's switch does not automatically "fall through"; every non-empty case must end with break, return, throw, or continue. If you want to achieve a fall-through effect, use continue with a label.
switch expression (Dart 3.0+)
Dart 3.0 introduced switch expressions, which can directly produce values, making the syntax more concise.
Example
String day = 'Wednesday';
// switch expression: directly returns a value
String mood = switch (day) {
'Monday' => 'A little sleepy',
'Tuesday' => 'Starting to adapt',
'Wednesday' => 'Full of energy',
'Thursday' => 'Looking forward to the weekend',
'Friday' => 'In a cheerful mood',
'Saturday' || 'Sunday' => 'Carefree',
_ => 'Unknown' // _ is a wildcard, equivalent to default
};
print('EXAMPLE mood: $mood');
}
EXAMPLE 心情: 干劲十足
switch expressions require covering all possible cases; the compiler will help you check for omissions.
for Loop
The for loop is the most common loop structure, suitable when you know the number of iterations.
Standard for loop
Example
// Standard for loop: initialization; condition; update
for (int i = 1; i <= 5; i++) {
print('EXAMPLE loop $i');
}
// The loop variable can also be declared outside
int j = 0;
for (; j < 3; j++) {
print('j = $j');
}
}
EXAMPLE 第 1 次循环 EXAMPLE 第 2 次循环 EXAMPLE 第 3 次循环 EXAMPLE 第 4 次循环 EXAMPLE 第 5 次循环 j = 0 j = 1 j = 2
for-in loop (traversing collections)
for-in is the simplest way to iterate over collections like List and Set.
Example
List<String> fruits = [Apple, Banana, Orange, 'Grape'];
// for-in: iterates over the elements in the collection one by one
for (var fruit in fruits) {
print(EXAMPLE Fruit: $fruit);
}
}
EXAMPLE 水果: 苹果 EXAMPLE 水果: 香蕉 EXAMPLE 水果: 橙子 EXAMPLE 水果: 葡萄
forEach method
List and Set also provide the forEach method, which uses a callback function to process each element.
Example
List<int> scores = [85, 92, 78, 60];
// forEach: execute the callback function for each element
scores.forEach((score) {
String result = score >= 60 ? 'Pass' : 'Fail';
print(EXAMPLE Score: $score -> $result);
});
}
EXAMPLE 分数: 85 -> 及格 EXAMPLE 分数: 92 -> 及格 EXAMPLE 分数: 78 -> 及格 EXAMPLE 分数: 60 -> 及格
while and do-while loops
The while loop checks the condition before each iteration, suitable for scenarios where the number of iterations is uncertain.
Example
// while: check the condition first, then execute
int count = 3;
while (count > 0) {
print(EXAMPLE Countdown: $count);
count--; // Remember to update the condition variable, otherwise it will be an infinite loop
}
print(Launch!);
}
EXAMPLE 倒计时: 3 EXAMPLE 倒计时: 2 EXAMPLE 倒计时: 1 发射!
The difference between do-while and while is that it executes the loop body at least once, because the condition is checked at the end.
Example
// do-while: execute once first, then check the condition
int num = 0;
do {
print(EXAMPLE executes at least once, num = $num);
num++;
} while (num < 0); // The condition is false from the start
print(Loop ended, num = $num);
}
EXAMPLE 至少执行一次,num = 0 循环结束,num = 1
The do-while loop guarantees the loop body executes at least once, even if the condition is not met from the start. This is useful in "try first, then evaluate" scenarios, such as reading user input until it is valid.
while vs for: How to choose
| Scenarios | Recommended loop | Reason |
|---|---|---|
| Determinate Number of Iterations | for | Initialization, condition, and update written together, clear at a glance |
| Indeterminate Number of Iterations | while | Focus Only on the Condition, More Flexible |
| Executes at Least Once | do-while | Execute First, Then Evaluate |
| Traversing collections | for-in or forEach | The most concise way to iterate over collections |
break and continue
break is used to immediately exit the entire loop, while continue is used to skip the current iteration and move to the next.
Example
// break: stop the loop immediately after finding the target
List<String> names = ['Alice', 'Bob', 'example', 'David'];
for (var name in names) {
print(Check: $name);
if (name == 'example') {
print(Found EXAMPLE!);
break; // Exit the loop, no longer checking the following elements
}
}
print(---separator---);
// continue: skip the current iteration
for (int i = 1; i <= 5; i++) {
if (i == 3) {
continue; // skip the i=3 iteration
}
print('EXAMPLE iteration $i');
}
}
检查: Alice 检查: Bob 检查: example 找到 EXAMPLE 了! ---分隔线--- EXAMPLE 第 1 次 EXAMPLE 第 2 次 EXAMPLE 第 4 次 EXAMPLE 第 5 次
Labeled break and continue
In nested loops, labels allow you to jump out of a specified outer loop.
Example
// The label outerLoop marks the outer loop
outerLoop:
for (int i = 1; i <= 3; i++) {
for (int j = 1; j <= 3; j++) {
print('i=$i, j=$j');
if (i == 2 && j == 2) {
print('Target found, exit outer loop');
break outerLoop; // Break out of the outer loop labeled outerLoop
}
}
}
print('Loop ended');
}
i=1, j=1 i=1, j=2 i=1, j=3 i=2, j=1 i=2, j=2 找到目标,退出外层循环 循环结束
other extensionsLabels should be used with caution. In most cases, extracting nested loop logic into independent functions and using return to exit is clearer.