if / else — Decision Making
if / else — Decision Making
Every useful program needs to make decisions. Should we show a welcome message or an error? Is the user old enough? Did the login succeed? These are all conditional situations — and in Dart, we handle them with if, else if, and else.
🔹 The Basic if Statement
The simplest form: run a block of code only if a condition is true.
dartvoid main() { int age = 20; if (age >= 18) { print('You are an adult.'); } }
- The condition inside
()must evaluate to abool(trueorfalse). - The block inside
{}runs only when the condition istrue. - If the condition is
false, the block is simply skipped.
🔹 if-else
Use else to handle the case when the condition is false.
dartvoid main() { int age = 15; if (age >= 18) { print('Access granted.'); } else { print('Access denied. You must be 18+.'); } }
Output: Access denied. You must be 18+.
Tip: Always use curly braces {} even for single-line blocks. It prevents hard-to-find bugs when you add lines later.
🔹 if-else if-else Chains
When you have more than two possibilities, chain multiple conditions:
dartvoid main() { int score = 75; 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'); } }
Output: Grade: C
Dart checks each condition top to bottom and executes only the first block whose condition is true. The rest are skipped.
🔹 Boolean Conditions
Conditions must be bool in Dart. Unlike JavaScript or C, Dart does not treat 0, null, or empty strings as false.
dartvoid main() { bool isLoggedIn = true; // Correct — using a bool directly if (isLoggedIn) { print('Welcome back!'); } // ERROR in Dart — non-boolean used as condition // int x = 0; // if (x) { ... } // This does NOT compile! }
🔹 Relational Operators in Conditions
| Operator | Meaning |
|---|---|
== | Equal to |
!= | Not equal to |
> | Greater than |
< | Less than |
>= | Greater than or equal |
<= | Less than or equal |
dartvoid main() { int a = 10, b = 20; if (a != b) { print('a and b are different'); } if (a <= b) { print('a is less than or equal to b'); } }
🔹 Logical Operators in Conditions
Combine multiple conditions using logical operators:
| Operator | Meaning |
|---|---|
&& | AND — both must be true |
|| | OR — at least one must be true |
! | NOT — flips true/false |
dartvoid main() { int age = 25; bool hasTicket = true; // AND — both conditions must be true if (age >= 18 && hasTicket) { print('You may enter the event.'); } // OR — at least one must be true bool isAdmin = false; bool isModerator = true; if (isAdmin || isModerator) { print('You have elevated access.'); } // NOT — flip a condition bool isBanned = false; if (!isBanned) { print('Account is active.'); } }
🔹 Nested if Statements
You can place if statements inside other if blocks:
dartvoid main() { bool hasAccount = true; String password = 'secret123'; if (hasAccount) { if (password == 'secret123') { print('Login successful!'); } else { print('Wrong password.'); } } else { print('Please create an account first.'); } }
Warning: Avoid deep nesting! More than 2–3 levels of nested if statements makes code very hard to read and maintain. Consider refactoring with early returns or helper functions.
🔹 Common Patterns
Range Check
dartvoid main() { int temperature = 22; if (temperature >= 20 && temperature <= 30) { print('Comfortable temperature.'); } else if (temperature < 20) { print("It's cold. Grab a jacket!"); } else { print("It's hot. Stay hydrated!"); } }
Null Check
dartvoid main() { String? username; // nullable String if (username != null) { print('Hello, $username!'); } else { print('Hello, Guest!'); } }
Type Check with is
Use the is keyword to check the runtime type of a variable:
dartvoid main() { dynamic value = 42; if (value is int) { print('It is an integer: $value'); } else if (value is String) { print('It is a string: $value'); } else { print('Unknown type'); } }
After if (value is int), Dart smart-casts value to int automatically inside that block — no explicit casting needed!
🔹 Real-World Examples
Example 1: Age Verification
dartvoid checkAge(int age) { if (age < 0) { print('Invalid age.'); } else if (age < 13) { print('Child'); } else if (age < 18) { print('Teenager'); } else if (age < 65) { print('Adult'); } else { print('Senior'); } } void main() { checkAge(10); // Child checkAge(17); // Teenager checkAge(30); // Adult checkAge(70); // Senior }
Example 2: Grade System
dartString getGrade(int score) { if (score < 0 || score > 100) { return 'Invalid score'; } else if (score >= 90) { return 'A — Excellent'; } else if (score >= 80) { return 'B — Good'; } else if (score >= 70) { return 'C — Average'; } else if (score >= 60) { return 'D — Below Average'; } else { return 'F — Fail'; } } void main() { print(getGrade(95)); // A — Excellent print(getGrade(73)); // C — Average print(getGrade(45)); // F — Fail }
Example 3: Login Validation
dartvoid login(String username, String password) { if (username.isEmpty || password.isEmpty) { print('Username and password are required.'); return; } if (username.length < 3) { print('Username must be at least 3 characters.'); return; } if (password.length < 6) { print('Password must be at least 6 characters.'); return; } // If all checks pass: print('Credentials look valid. Logging in...'); } void main() { login('', 'pass'); // Username and password are required. login('ab', 'password'); // Username must be at least 3 characters. login('alice', '123'); // Password must be at least 6 characters. login('alice', 'secret'); // Credentials look valid. Logging in... }
Note: Using early return inside an if block (called a guard clause) is a great way to flatten nested conditions and make your code more readable.
Summary
| Concept | Purpose |
|---|---|
if | Run code only when condition is true |
else | Handle the false case |
else if | Check multiple conditions in sequence |
&&, ||, ! | Combine or negate boolean conditions |
is | Check the runtime type of a variable |
Nested if | Conditional logic inside another condition |
| Guard clauses | Early returns to avoid deep nesting |
Mastering if/else is the foundation of all program logic. In the next lesson, we'll explore switch statements and Dart 3's powerful pattern matching for cleaner multi-branch logic!