# Control flow statements

Domains:

You can control the flow of your Dart code using any of the following:

• if and else
• for loops
• while and do-while loops
• break and continue
• switch and case
• assert

You can also affect the control flow using try-catch and throw, as explained in Exceptions.

## If and else

Dart supports if statements with optional else statements, as the next sample shows. Also see dart-tour-operators ">conditional expressions.

if (isRaining()) {
you.bringRainCoat();
} else if (isSnowing()) {
you.wearJacket();
} else {
car.putTopDown();
}


Unlike JavaScript, conditions must use boolean values, nothing else. See dart-tour-built-in-types ">Booleansfor more information.

## For loops

You can iterate with the standard for loop. For example:

var message = StringBuffer('Dart is fun');
for (var i = 0; i < 5; i++) {
message.write('!');
}


Closures inside of Dart’s for loops capture the value of the index, avoiding a common pitfall found in JavaScript. For example, consider:

var callbacks = [];
for (var i = 0; i < 2; i++) {
}
callbacks.forEach((c) => c());


The output is 0 and then 1, as expected. In contrast, the example would print 2 and then 2 in JavaScript.

If the object that you are iterating over is an Iterable, you can use the forEach() method. Using forEach() is a good option if you don’t need to know the current iteration counter:

candidates.forEach((candidate) => candidate.interview());


Iterable classes such as List and Set also support the for-in form of iteration:

var collection = [0, 1, 2];
for (var x in collection) {
print(x); // 0 1 2
}


## While and do-while

A while loop evaluates the condition before the loop:

while (!isDone()) {
doSomething();
}


A do-while loop evaluates the condition after the loop:

do {
printLine();
} while (!atEndOfPage());


## Break and continue

Use break to stop looping:

while (true) { if (shutDownRequested()) break; processIncomingRequests(); }


Use continue to skip to the next loop iteration:

for (int i = 0; i < candidates.length; i++) {
var candidate = candidates[i];
if (candidate.yearsExperience < 5) {
continue;
}
candidate.interview();
}


You might write that example differently if you’re using an Iterable such as a list or set:

candidates
.where((c) => c.yearsExperience >= 5)
.forEach((c) => c.interview());


## Switch and case

Switch statements in Dart compare integer, string, or compile-time constants using ==. The compared objects must all be instances of the same class (and not of any of its subtypes), and the class must not override ==. Enumerated types work well in switch statements.

Note: Switch statements in Dart are intended for limited circumstances, such as in interpreters or scanners.

Each non-empty case clause ends with a break statement, as a rule. Other valid ways to end a non-empty case clause are a continue, throw, or return statement.

Use a default clause to execute code when no case clause matches:

var command = 'OPEN';
witch (command) {
case 'CLOSED':
executeClosed();
break;
case 'PENDING':
executePending();
break;
case 'APPROVED':
executeApproved();
break;
case 'DENIED':
executeDenied();
break;
case 'OPEN':
executeOpen();
break;
default:
executeUnknown();
}


The following example omits the break statement in a case clause, thus generating an error:

var command = 'OPEN';
switch (command) {
case 'OPEN':
executeOpen(); // ERROR: Missing break
case 'CLOSED':
executeClosed();
break;
}


However, Dart does support empty case clauses, allowing a form of fall-through:

var command = 'CLOSED';
switch (command) {
case 'CLOSED': // Empty case falls through.
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}


If you really want fall-through, you can use a continue statement and a label:

var command = 'CLOSED';
switch (command) {
case 'CLOSED':
executeClosed();
continue nowClosed; // Continues executing at the nowClosed label.

nowClosed:
case 'NOW_CLOSED':
// Runs for both CLOSED and NOW_CLOSED.
executeNowClosed();
break;
}


A case clause can have local variables, which are visible only inside the scope of that clause.

## Assert

During development, use an assert statement — assert(condition, optionalMessage); — to disrupt normal execution if a boolean condition is false. Here are some more:

// Make sure the variable has a non-null value.
assert(text != null);

// Make sure the value is less than 100.
assert(number < 100);

// Make sure this is an https URL.
assert(urlString.startsWith('https'));


To attach a message to an assertion, add a string as the second argument to assert.

assert(urlString.startsWith('https'),


The first argument to assert can be any expression that resolves to a boolean value. If the expression’s value is true, the assertion succeeds and execution continues. If it’s false, the assertion fails and an exception (an AssertionError) is thrown.

When exactly do assertions work? That depends on the tools and framework you’re using:

Flutter enables assertions in debug mode.

Development-only tools such as dartdevc typically enable assertions by default.

Some tools, such as dart and dart2js, support assertions through a command-line flag: --enable-asserts.

In production code, assertions are ignored, and the arguments to assert aren’t evaluated.

Page structure
Terms