On this page25 sections
- Prerequisites
- Connection With Previous Lectures
- Learning Objectives
- 1. The if-else Statement
- 2. else Has No Condition
- 3. Many Options with else if
- 4. Order Matters
- 5. The Final else Is Optional
- 6. Nested if
- 7. Flattening a Nested if
- 8. Assigning a Value in Every Branch
- 9. Promotion in the else Branch
- 10. Revisiting the Conditional Expression
- 11. Choosing Between if-else and ? :
- 12. Chained ? : versus else if
- 13. A Real-World Example
- Code Examples
- Common Beginner Mistakes
- Best Practices
- Mini Challenge
- Practice Questions
- Practice Answers
- Quick Revision
- Key Takeaways
- What's Next?
Lecture 23 — if-else, else-if & Conditional Expressions
| Category | 5 — Control Flow |
| Lecture | 023 of 140 |
| Estimated video length | 16 min |
| Target | Dart 3.12.2 |
| Level | Beginner |
A single
ifcan only say "do this, or do nothing". Withelseandelse if, a program picks exactly one path out of two, three, or ten — and? :does the same for a value.
Contents
Prerequisites · Connection · Objectives · Lesson · Code Examples · Common Mistakes · Best Practices · Mini Challenge · Practice Questions · Answers · Takeaways
Every error message in this lecture is real. Each one was produced by running the code shown on Dart 3.12.2, so you will recognize it when you meet it yourself.
Prerequisites
Students should already understand, from Lectures 004–022:
- variables,
var,final, and string interpolation with$and${...} - nullable types such as
String?andint.tryParse(Lectures 012–013) - comparison operators and logical operators
&&,||,!(Lectures 018–019) - the conditional expression
condition ? a : b(Lecture 020) - the
ifstatement, its condition, its{ }block, and promotion after!= null(Lecture 022)
Connection With Previous Lectures
In Lecture 022, an if ran its block only when the condition was true. To report both
results — pass or fail — we would need two ifs:
if (mark >= 50) {
print('Pass');
}
if (mark < 50) {
print('Fail');
}This works, but asks the same question twice, once backwards. Change 50 to 40 in one line
and forget the other, and a mark of 45 prints both words. What we mean is one decision
with two outcomes. Dart has a word for "otherwise": else.
Learning Objectives
By the end of this lecture you will be able to:
- Write an
if-elsestatement that runs exactly one of two blocks - Build an
else-ifchain that chooses between many options - Order the conditions in a chain so the right branch wins
- Nest an
ifinside another, and flatten it when that reads better - Give a variable its value in every branch of an
if-else - Use promotion after a
nullcheck in theelsebranch - Compare
if-elsewith the conditional expression? :and choose between them - Recognize the errors and silent bugs that
elsemistakes cause
1. The if-else Statement
if (condition) {
// runs when condition is true
} else {
// runs when condition is false
}void main() {
var mark = 42;
if (mark >= 50) {
print('Pass');
} else {
print('Fail');
}
}FailAnalogy — a fork in a road. You must take one branch, and you cannot take both.
ifis the left branch,elseis the right branch.
Exactly one block runs, every time. else means "in every other case".
2. else Has No Condition
else already means "the condition was false", so it never takes a condition of its own.
Writing one confuses Dart badly:
void main() {
var mark = 40;
if (mark >= 50) {
print('Pass');
} else (mark < 50) { // ✗
print('Fail');
}
}Error: Expected ')' before this.
} else (mark < 50) { // ✗
^
Error: Expected ';' after this.
}
^The messages point at odd places, because Dart tried to read (mark < 50) { as a separate
statement. For a second condition, use else if.
3. Many Options with else if
Real decisions often have more than two outcomes. An else-if chain asks one question after another:
void main() {
var mark = 72;
if (mark >= 80) {
print('Grade A');
} else if (mark >= 60) {
print('Grade B');
} else if (mark >= 50) {
print('Grade C');
} else {
print('Grade F');
}
}Grade BDart checks the conditions from top to bottom. 72 >= 80 is false, so it moves on.
72 >= 60 is true, so it prints Grade B — and skips everything else in the chain,
even though 72 >= 50 is also true. The first true condition wins.
4. Order Matters
Because the first true condition wins, a chain in the wrong order gives wrong answers with
no error message:
void main() {
var mark = 95;
if (mark >= 50) {
print('Grade C');
} else if (mark >= 80) {
print('Grade A');
} else {
print('Grade F');
}
}Grade CA mark of 95 stops at the first test, 95 >= 50, and never reaches the A branch. When
conditions overlap, put the narrowest one first: the highest mark, then the next.
5. The Final else Is Optional
A chain may end without an else. Then, if no condition is true, nothing runs at all:
void main() {
var temperature = 22;
if (temperature >= 35) {
print('Heat warning!');
} else if (temperature <= 0) {
print('Frost warning!');
}
print('Forecast done.');
}Forecast done.Leave out the else when "none of these" means "nothing to do". Keep it when every case
needs an answer, like a grade.
6. Nested if
A block can contain any statements — including another if. That is a nested if:
void main() {
var age = 20;
var hasTicket = false;
if (age >= 18) {
if (hasTicket) {
print('Welcome in!');
} else {
print('Please buy a ticket.');
}
} else {
print('Adults only.');
}
}Please buy a ticket.Only adults reach the inner question about the ticket. Each else belongs to the if whose
block it closes — the braces make that clear.
Editor hint. When a
boolvariable is set straight totrueorfalse, as in many programs in this lecture, your editor may grey out a branch with the hint "Dead code". Dart can see that branch can never run with this value. The program still works; in real programs the value comes from input, and every branch is live.
7. Flattening a Nested if
A flat else-if chain is often easier to read. This program gives the same answers:
void main() {
var age = 20;
var hasTicket = false;
if (age < 18) {
print('Adults only.');
} else if (hasTicket) {
print('Welcome in!');
} else {
print('Please buy a ticket.');
}
}Please buy a ticket.Reaching else if (hasTicket) already means age < 18 was false. A flat chain reads like a
list of rules.
8. Assigning a Value in Every Branch
Often each branch decides a value. Declare the variable first, then assign it in every
branch. It can even be final, because each run assigns it exactly once:
void main() {
var mark = 72;
final String result;
if (mark >= 50) {
result = 'Pass';
} else {
result = 'Fail';
}
print(result);
}PassDart checks that every path gives the variable a value. Remove the final else from a
chain, and one path is left without a value:
void main() {
var mark = 72;
String grade;
if (mark >= 80) {
grade = 'A';
} else if (mark >= 60) {
grade = 'B';
}
print(grade); // ✗
}Error: Non-nullable variable 'grade' must be assigned before it can be used.
print(grade); // ✗
^^^^^Dart does not look at the value 72: a mark below 60 would reach print with no grade.
Adding else { grade = 'C'; } fixes it.
9. Promotion in the else Branch
In Lecture 022, Dart promoted a nullable variable inside if (x != null). After
if (x == null), the same happens in the else branch:
void main() {
var input = 'Zed';
String? nickname = input.isEmpty ? null : input;
if (nickname == null) {
print('No nickname set.');
} else {
print('Nickname has ${nickname.length} letters.');
}
}Nickname has 3 letters.nickname.length would be rejected on a String?. Inside else, the null case is already
handled, so it is allowed — no ! needed.
10. Revisiting the Conditional Expression
In Lecture 020 you met condition ? a : b. It asks the same yes-or-no question as if-else,
but it produces a value instead of running blocks. Here is one decision written both ways:
void main() {
var mark = 72;
String result1;
if (mark >= 50) {
result1 = 'Pass';
} else {
result1 = 'Fail';
}
var result2 = mark >= 50 ? 'Pass' : 'Fail';
print(result1);
print(result2);
}Pass
Passif-else is a statement: it does things. ? : is an expression: it is a value,
so it fits after = or inside ${...}, where an if statement cannot go.
11. Choosing Between if-else and ? :
Use ? : when… | Use if-else when… |
|---|---|
| you choose between two values | you choose between actions (statements) |
| each side is short | a branch needs several lines |
the result goes into a variable or ${...} | there are three or more outcomes |
When each branch does more than produce one value, if-else is the right tool:
void main() {
var balance = 300;
var price = 450;
if (balance >= price) {
balance -= price;
print('Paid $price. Balance: $balance');
} else {
var missing = price - balance;
print('Declined. You need $missing more.');
}
}Declined. You need 150 more.The else branch holds two statements, which a conditional expression cannot.
12. Chained ? : versus else if
In Lecture 021 you saw that ? : can be chained:
void main() {
var mark = 72;
var grade = mark >= 80
? 'A'
: mark >= 60
? 'B'
: 'C';
print(grade);
}BIt is correct, but compare it with the chain in section 3: the else-if version shows each
rule on its own line. A good habit: one ? per expression. For three or more
outcomes, use else if — or the switch statement from the next lecture. Dart also has
switch expressions, which choose between many values neatly; we will study them in
Lecture 025 — Modern Switch Expressions.
13. A Real-World Example
A shop gives a discount based on the order total, and free delivery for members:
void main() {
var total = 6500;
var isMember = true;
final int discount;
if (total >= 10000) {
discount = 15;
} else if (total >= 5000) {
discount = 10;
} else if (total >= 2000) {
discount = 5;
} else {
discount = 0;
}
var finalTotal = total - total * discount ~/ 100;
var delivery = isMember ? 0 : 250;
print('Discount: $discount%');
print('To pay: ${finalTotal + delivery}');
print('Delivery: ${delivery == 0 ? 'free' : '$delivery'}');
}Discount: 10%
To pay: 5850
Delivery: freeAn else-if chain, ordered from the highest total down, assigns a final discount on every
path. Two short two-way choices use ? :. Each tool does the job it is best at.
Code Examples
Example 1 — Even or Odd
void main() {
var number = 7;
if (number % 2 == 0) {
print('$number is even');
} else {
print('$number is odd');
}
}7 is oddExample 2 — Positive, Negative, or Zero
void main() {
var number = -4;
if (number > 0) {
print('Positive');
} else if (number < 0) {
print('Negative');
} else {
print('Zero');
}
}NegativeExample 3 — Larger of Two Numbers
void main() {
var a = 18;
var b = 25;
var larger = a > b ? a : b;
print('Larger: $larger');
}Larger: 25Example 4 — Time of Day
void main() {
var hour = 15;
if (hour < 12) {
print('Good morning');
} else if (hour < 18) {
print('Good afternoon');
} else {
print('Good evening');
}
}Good afternoonExample 5 — Nested Check
void main() {
var username = 'sara';
var password = '1234';
if (username == 'sara') {
if (password == 'secret') {
print('Logged in');
} else {
print('Wrong password');
}
} else {
print('Unknown user');
}
}Wrong passwordExample 6 — Reading Input Safely
void main() {
var input = 'abc';
var age = int.tryParse(input);
if (age == null) {
print('"$input" is not a number.');
} else {
print('Next year you will be ${age + 1}.');
}
}"abc" is not a number.In the else branch, age is promoted from int? to int.
Example 7 — Student Report
void main() {
var name = 'Ali';
var mark = 86;
final String grade;
if (mark >= 80) {
grade = 'A';
} else if (mark >= 60) {
grade = 'B';
} else if (mark >= 50) {
grade = 'C';
} else {
grade = 'F';
}
print('$name: $mark (${grade == 'F' ? 'failed' : 'passed'}, grade $grade)');
}Ali: 86 (passed, grade A)Example 8 — Shopping Total with Shipping
void main() {
var price = 1200;
var quantity = 2;
var subtotal = price * quantity;
var shipping = subtotal >= 2000 ? 0 : 200;
print('Subtotal: $subtotal');
print('Shipping: $shipping');
print('Total: ${subtotal + shipping}');
}Subtotal: 2400
Shipping: 0
Total: 2400Example 9 — Bank Withdrawal
void main() {
var balance = 1000;
var amount = 1200;
if (amount <= 0) {
print('Enter a positive amount.');
} else if (amount > balance) {
print('Insufficient funds. Balance: $balance');
} else {
balance -= amount;
print('Withdrew $amount. Balance: $balance');
}
}Insufficient funds. Balance: 1000The invalid amount is rejected first, so later branches can assume it is positive. Only
the last branch changes balance.
Example 10 — Temperature Advice
void main() {
var celsius = 31.5;
String advice;
if (celsius >= 30) {
advice = 'Stay hydrated.';
} else if (celsius >= 15) {
advice = 'Enjoy the weather.';
} else {
advice = 'Take a jacket.';
}
print('$celsius°C — $advice');
}31.5°C — Stay hydrated.Common Beginner Mistakes
1. Giving else a condition — } else (mark < 50) {
Error: Expected ')' before this.else never has a condition. Use else if (...) when you need one.
2. Conditions in the wrong order
if (mark >= 50) before else if (mark >= 80) gives every high mark a C (section 4). No
error — just wrong answers. Put the narrowest condition first.
3. A semicolon after the condition
void main() {
var mark = 40;
if (mark >= 50); {
print('Pass');
}
}PassThe ; ends the if with an empty statement, so the block below runs always. dart analyze warns Unnecessary empty statement., and dart format moves the ; onto its own
line, where the bug is easy to see.
4. Leaving a path without a value (section 8)
Error: Non-nullable variable 'grade' must be assigned before it can be used.Add a final else so every path assigns the variable.
5. Declaring the variable inside the branches
void main() {
var mark = 72;
if (mark >= 50) {
var result = 'Pass';
} else {
var result = 'Fail';
}
print(result); // ✗
}Error: Undefined name 'result'.
print(result); // ✗
^^^^^^A variable declared inside a { } block exists only inside that block. Declare it
before the if, then assign it in each branch.
6. Using ? : to run actions
mark >= 50 ? print('Pass') : print('Fail'); runs, but hides two actions inside an
expression. Write if-else.
Best Practices
- Use
if-elsefor two outcomes, not two oppositeifs. - Order an
else-ifchain from the narrowest condition to the widest. - End a chain with
elsewhen every case needs an answer. - Always use braces
{ }, even for one-line branches. - Prefer a flat
else-ifchain over deep nesting. - Declare the variable before the
ifand assign it in every branch —finalif possible. - Use
? :for a short choice between two values; never chain more than one?.
Mini Challenge
Sara's phone shows a battery message. Store battery = 15 and isCharging = false. If the
phone is charging, print Charging.... Otherwise print Battery low! below 20, Battery OK below 80, and Battery full from 80 up. On a second line, print Level: 15%.
Battery low!
Level: 15%Try it yourself before opening the solution.
Show solution
void main() {
var battery = 15;
var isCharging = false;
if (isCharging) {
print('Charging...');
} else if (battery < 20) {
print('Battery low!');
} else if (battery < 80) {
print('Battery OK');
} else {
print('Battery full');
}
print('Level: $battery%');
}Battery low!
Level: 15%Charging is checked first, because it overrides every level message.
Practice Questions
Work through these in order — they run from beginner to application to challenge.
Beginner
- Store
age = 16. PrintCan voteifageis at least18, otherwiseToo young. - Store
number = 0. PrintPositive,Negative, orZerousing anelse-ifchain. - Rewrite this
if-elseas a single line with? :, storing the result instatus, then print it:if (isOpen) { status = 'Open'; } else { status = 'Closed'; }withisOpen = false.
Application
- Store
mark = 55. Print the grade:Afrom 80,Bfrom 60,Cfrom 50, otherwiseF. - Store
price = 900andbalance = 750. If the balance covers the price, subtract it and printBought! Balance: …; otherwise printShort by …. - Store
celsius = -3. Using? :inside the interpolation, print-3°C: below freezing(orabove freezingfrom0up). - Store
var input = '';andString? name = input.isEmpty ? null : input;. Ifnameisnull, printHello, guest!; otherwise print the name and its length asHello, Ali (3 letters). - Store
items = 3. PrintYou have 3 items.— butiteminstead ofitemswhen the count is1. Use? :inside the interpolation.
Challenge
-
This program prints the wrong grade for
mark = 92. Find the bug and fix it:if (mark >= 60) { print('B'); } else if (mark >= 90) { print('A'); } else { print('C'); } -
A cinema ticket costs
800. Children under12pay half, people60and over pay500, and students (any age from 12 to 59) pay600. Storeage = 21andisStudent = true, assign the price to afinal intin anelse-ifchain, and printTicket: 600.
Practice Answers
Question 1 — Solution
void main() {
var age = 16;
if (age >= 18) {
print('Can vote');
} else {
print('Too young');
}
}Too youngQuestion 2 — Solution
void main() {
var number = 0;
if (number > 0) {
print('Positive');
} else if (number < 0) {
print('Negative');
} else {
print('Zero');
}
}ZeroQuestion 3 — Solution
void main() {
var isOpen = false;
var status = isOpen ? 'Open' : 'Closed';
print(status);
}ClosedQuestion 4 — Solution
void main() {
var mark = 55;
if (mark >= 80) {
print('A');
} else if (mark >= 60) {
print('B');
} else if (mark >= 50) {
print('C');
} else {
print('F');
}
}CQuestion 5 — Solution
void main() {
var price = 900;
var balance = 750;
if (balance >= price) {
balance -= price;
print('Bought! Balance: $balance');
} else {
print('Short by ${price - balance}');
}
}Short by 150Question 6 — Solution
void main() {
var celsius = -3;
print('$celsius°C: ${celsius < 0 ? 'below' : 'above'} freezing');
}-3°C: below freezingQuestion 7 — Solution
void main() {
var input = '';
String? name = input.isEmpty ? null : input;
if (name == null) {
print('Hello, guest!');
} else {
print('Hello, $name (${name.length} letters)');
}
}Hello, guest!With input = 'Ali' the else branch runs and prints Hello, Ali (3 letters); name.length
is allowed there because of promotion.
Question 8 — Solution
void main() {
var items = 3;
print('You have $items ${items == 1 ? 'item' : 'items'}.');
}You have 3 items.Question 9 — Solution
void main() {
var mark = 92;
if (mark >= 90) {
print('A');
} else if (mark >= 60) {
print('B');
} else {
print('C');
}
}A92 >= 60 was true, so the old chain stopped at B. The narrower >= 90 must come first.
Question 10 — Solution
void main() {
var age = 21;
var isStudent = true;
final int price;
if (age < 12) {
price = 400;
} else if (age >= 60) {
price = 500;
} else if (isStudent) {
price = 600;
} else {
price = 800;
}
print('Ticket: $price');
}Ticket: 600Reaching else if (isStudent) already means the age is 12–59, so no range check is needed.
Quick Revision
- How many blocks of an
if-elserun? - Why can
elsenever have a condition? - In an
else-ifchain, which branch runs when several conditions aretrue? - What happens when no condition is
trueand there is no finalelse? - Why may a
finalvariable be assigned in both branches of anif-else? - After
if (x == null) { ... }, what does Dart know aboutxin theelsebranch? - What is the difference between
if-elseand? :? - What does a semicolon right after
if (...)do?
Key Takeaways
if-elseruns exactly one of two blocks;elsemeans "in every other case" and has no condition.- An
else-ifchain checks conditions top to bottom, and the firsttrueone wins. - Order overlapping conditions from narrowest to widest — the wrong order is a silent bug.
- The final
elseis optional; without it, possibly no branch runs. - A variable — even a
finalone — can be assigned in every branch, and Dart checks that no path is left out. - After
if (x == null), theelsebranch treatsxas non-nullable. ? :chooses a value;if-elsechooses actions. Use? :for short two-way choices andelse iffor three or more.
What's Next?
Lecture 024 — switch Statements. An else-if chain can compare one value against many
possibilities, but it repeats the variable in every condition: day == 'Mon', day == 'Tue',
… A switch statement names the value once and lists the cases beneath it — cleaner when one
value decides between many fixed options.