100 Questions to Master Dart Fundamentals
This is Part 10 — the capstone of the Dart Fundamentals series. The previous parts taught the concepts; this bank turns them into mastery.
How to use this bank:
- 100 questions, grouped by topic, tagged [Basic], [Medium], or [Advanced], and marked (Theory) or (Coding).
- Each has a collapsible Hint & Solution. Try it cold first — the struggle before you peek is where the learning happens. The hint gives you the idea; the solution confirms it.
- For (Coding) questions, actually run your Dart at dartpad.dev — no setup needed. Code you don't run is code you don't understand yet.
- Don't binge. Do 10–15 a day, and re-attempt anything you needed help with a week later.
Topics map to the series:
| Section | Topic | Part | | --- | --- | --- | | A | Type system & inference | Part 4 | | B | Null safety | Part 5 | | C | Collections | Part 6 | | D | Functions | Part 7 | | E | String manipulation | Part 8 | | F | Control flow & patterns | Part 9 |
Let's go.
Section A — Type System & Inference (Q1–14)
Q1. [Basic] (Theory) Does var x = 10; make x able to change type later? Why or why not?
Hint & Solution
Hint: var is about inference, not flexibility.
Solution: No. var infers the type once (int here) and locks it permanently. x = 'hi' is a compile error. The keyword that allows the type to change is dynamic.
Q2. [Basic] (Theory) What's the inferred type of var y = 3 / 4;? Why might it surprise a beginner?
Hint & Solution
Hint: Recall the division gotcha from Part 3.
Solution: double. The / operator always returns a double, even for two ints — so y is 0.75, not 0.
Q3. [Basic] (Coding) Declare an empty list intended to hold strings, correctly typed, then add one.
Hint & Solution
Hint: An empty literal can't infer its element type — annotate it.
Solution:
var names = <String>[]; // or: List<String> names = [];
names.add('Asha');
var names = [] would infer List<dynamic> — a trap.
Q4. [Basic] (Theory) What's the difference between Object and dynamic?
Hint & Solution
Hint: One keeps the type checker on; the other switches it off.
Solution: Object is a real type — it accepts any non-null value but the compiler still checks every member access. dynamic disables type checking, so member access compiles even when it's wrong and crashes at runtime.
Q5. [Medium] (Theory) Why is Object? called Dart's "top type"?
Hint & Solution
Hint: What's the one value Object excludes?
Solution: Every value in Dart is an Object except null. Adding ? includes null too, so Object? is the single type that every possible value fits into — the top of the type hierarchy.
Q6. [Medium] (Coding) Given Object value, print its length only if it's a String, with no cast and no crash risk.
Hint & Solution
Hint: is plus type promotion.
Solution:
if (value is String) {
print(value.length); // promoted to String here
}
Q7. [Medium] (Theory) What does is do that as doesn't, and when must you use as?
Hint & Solution
Hint: One promotes safely; the other asserts and can throw.
Solution: is tests a type and promotes the variable inside the guarded block (safe). as forcibly casts and throws a TypeError if wrong. Use as only when you're certain, or when you can't structure the code as an if to get promotion.
Q8. [Medium] (Coding) What's the inferred type of var d = [1, 2.0, 3];? Verify your reasoning.
Hint & Solution
Hint: Find the nearest common supertype of int and double.
Solution: List<num>. int and double both extend num, so the least common type of the elements is num. (Check with print(d.runtimeType) or your IDE.)
Q9. [Medium] (Theory) Why does var x; x = 5; (split across two lines) make x dynamic, and how do you avoid it?
Hint & Solution
Hint: Inference needs something on the right-hand side at declaration.
Solution: With no initializer there's nothing to infer from, so x defaults to dynamic. Avoid it by initializing on the same line (var x = 5;) or annotating the type (int x;).
Q10. [Medium] (Coding) Write a function safeLength(Object o) returning the length if o is a String or a List, else -1.
Hint & Solution
Hint: Two is checks, both promote.
Solution:
int safeLength(Object o) {
if (o is String) return o.length;
if (o is List) return o.length;
return -1;
}
Q11. [Advanced] (Theory) Explain "static type" vs "runtime type" using Object x = 42;.
Hint & Solution
Hint: What the compiler tracks vs. what's actually in memory.
Solution: The static type of x is Object (what the compiler enforces). The runtime type is int — x.runtimeType returns int, the actual class of the stored value. They can differ; that's why x is int is true even though it's declared Object.
Q12. [Advanced] (Theory) Why prefer is over .runtimeType == int for branching?
Hint & Solution
Hint: Subtypes.
Solution: is respects subtyping (a subclass instance is its supertype), and it promotes the variable. runtimeType == is an exact-class equality check that fails for subclasses and gives no promotion — fragile and unidiomatic.
Q13. [Advanced] (Coding) A JSON value arrives as dynamic data. Convert it to an int safely, returning 0 if it isn't actually an int.
Hint & Solution
Hint: Don't trust dynamic — test before use.
Solution:
int asInt(dynamic data) => data is int ? data : 0;
The is int both checks and promotes, so data is usable as an int in the true branch.
Q14. [Advanced] (Theory) Why is a function full of dynamic parameters considered a code smell even though it "works"?
Hint & Solution
Hint: Where do the bugs surface?
Solution: dynamic defers all type errors to runtime, so mistakes reach users instead of being caught while you type. It also kills autocomplete and refactoring safety. Prefer concrete types or Object? + is so the compiler does the checking.
Section B — Null Safety (Q15–32)
Q15. [Basic] (Theory) What does "non-nullable by default" mean?
Hint & Solution
Hint: What can a plain int hold?
Solution: A plain type (int, String) can never be null. To allow null you must opt in with ? (int?). This makes "might be missing" visible in the type itself.
Q16. [Basic] (Coding) Fix this so it compiles: int? n = 10; int doubled = n * 2;
Hint & Solution
Hint: n might be null, so prove it isn't — or supply a default.
Solution:
int doubled = (n ?? 0) * 2;
// or:
if (n != null) { int doubled = n * 2; }
Q17. [Basic] (Theory) Read String? aloud. What does the ? mean?
Hint & Solution
Hint: Two possibilities.
Solution: "A String, or null." The ? makes the type nullable — a distinct type from String, which the compiler forces you to null-check before use.
Q18. [Basic] (Coding) Print name, or 'Guest' if it's null, in one line.
Hint & Solution
Hint: The "if null, use this" operator.
Solution:
print(name ?? 'Guest');
Q19. [Basic] (Coding) Given String? s, get its length as an int? without crashing on null.
Hint & Solution
Hint: Safe-call operator.
Solution:
int? len = s?.length; // null in → null out
Q20. [Medium] (Theory) Difference between ?. and !?
Hint & Solution
Hint: One is safe; one is a promise that can break.
Solution: ?. is safe — it returns null instead of calling on a null receiver. ! asserts non-null and throws at runtime if the value is actually null. Prefer ?./??; use ! only when certain.
Q21. [Medium] (Coding) Write a one-liner for "the user's city, or 'Unknown' if user or address is null", given user?.address?.city.
Hint & Solution
Hint: Chain ?. then finish with ??.
Solution:
String city = user?.address?.city ?? 'Unknown';
Q22. [Medium] (Theory) What does ??= do? Give a one-line example.
Hint & Solution
Hint: Assign, but only when currently null.
Solution: It assigns the right side only if the variable is currently null. name ??= 'Anonymous'; sets name only when it was null; otherwise it's a no-op.
Q23. [Medium] (Coding) This crashes. Why, and how do you make it safe?
List<int?> xs = [1, null, 3];
var total = xs.fold(0, (sum, n) => sum + n!);
Hint & Solution
Hint: n! on the null element.
Solution: n! throws on the middle element. Replace the bang with a default:
var total = xs.fold(0, (sum, n) => sum + (n ?? 0)); // 4
Q24. [Medium] (Theory) Why does a Map lookup like ages['x'] return a nullable type?
Hint & Solution
Hint: The key might not exist.
Solution: A missing key yields null rather than crashing, so map[key] is typed V?. Null safety forces you to handle the miss, usually with ?? default.
Q25. [Medium] (Theory) When should a field be late instead of ??
Hint & Solution
Hint: Is it conceptually always present, just assigned later?
Solution: Use late when the value is genuinely non-null but can't be assigned at declaration (e.g. set in a constructor body or initState). Use ? only when the value can truly be absent. late keeps a clean non-null type without scattering !/?..
Q26. [Medium] (Coding) Give a Service class a non-null Database db assigned in a connect() method.
Hint & Solution
Hint: late, not nullable.
Solution:
class Service {
late Database db;
void connect() => db = Database();
}
Reading db before connect() throws a clear LateInitializationError.
Q27. [Medium] (Theory) What happens if you read a late variable before assigning it?
Hint & Solution
Hint: A specific runtime error, not a silent null.
Solution: You get a LateInitializationError at runtime — explicit and traceable, far better than a silent null propagating through your code.
Q28. [Advanced] (Coding) Use late for lazy initialization so an expensive computation runs at most once, only when first read.
Hint & Solution
Hint: late + an initializer expression defers execution.
Solution:
late final config = _loadConfig(); // _loadConfig runs on first read, then caches
If config is never read, _loadConfig() never runs.
Q29. [Advanced] (Theory) What makes Dart's null safety "sound," and why does soundness matter?
Hint & Solution
Hint: Can a non-nullable type ever be null at runtime?
Solution: Soundness means the guarantee is airtight: a non-nullable type cannot be null at runtime (barring ! lies). The compiler can optimize on that fact, and you can rely on it for correctness — no defensive null checks needed on plain types.
Q30. [Advanced] (Coding) Use the null-aware spread to build ['post', ...tags] where List<String>? tags might be null.
Hint & Solution
Hint: ...?.
Solution:
var all = ['post', ...?tags]; // skips tags entirely if null
Q31. [Advanced] (Theory) Why is a codebase littered with ! a design warning, not just a style nitpick?
Hint & Solution
Hint: What is ! working against?
Solution: Frequent ! usually means the data is being forced non-null instead of modelled honestly. Each ! is a potential runtime crash and a place the compiler's guarantee was overridden. The fix is usually to make the type properly nullable (and handle it) or non-nullable (and guarantee it), not to assert.
Q32. [Advanced] (Coding) Write firstEven(List<int> xs) returning the first even number, or null if none — typed correctly.
Hint & Solution
Hint: Return type must allow "none."
Solution:
int? firstEven(List<int> xs) {
for (final x in xs) {
if (x.isEven) return x;
}
return null;
}
The nullable return type makes "not found" explicit and forces callers to handle it.
Section C — Collections (Q33–52)
Q33. [Basic] (Theory) When do you choose a Set over a List?
Hint & Solution
Hint: Uniqueness and fast membership.
Solution: When you need unique values and/or fast "does it contain X?" checks, and order isn't the point. Lists keep order and allow duplicates but membership scans the whole thing.
Q34. [Basic] (Coding) Create a list of three colors and print the second one.
Hint & Solution
Hint: Indexes start at 0.
Solution:
var colors = ['red', 'green', 'blue'];
print(colors[1]); // green
Q35. [Basic] (Theory) What does {} create — a Set or a Map? How do you make the other one empty?
Hint & Solution
Hint: Ambiguity resolved in favor of one of them.
Solution: {} is an empty Map. For an empty Set you must annotate: <String>{}.
Q36. [Basic] (Coding) Deduplicate [1, 2, 2, 3, 3, 3] into a list of unique values.
Hint & Solution
Hint: Round-trip through a Set.
Solution:
[1, 2, 2, 3, 3, 3].toSet().toList(); // [1, 2, 3]
Q37. [Basic] (Coding) Make a Map from names to ages and print one age, handling a missing key with a default of 0.
Hint & Solution
Hint: Lookup is nullable.
Solution:
var ages = {'Asha': 30};
print(ages['Ben'] ?? 0); // 0
Q38. [Medium] (Coding) Merge defaults = {'a': 1, 'b': 2} and over = {'b': 9} so over wins.
Hint & Solution
Hint: Spread, and order matters.
Solution:
var merged = {...defaults, ...over}; // {a: 1, b: 9}
The later key wins in a map literal, so spread overrides last.
Q39. [Medium] (Coding) Build a list of the squares of [1,2,3,4] using collection-for.
Hint & Solution
Hint: [for (...) expr].
Solution:
var squares = [for (final n in [1,2,3,4]) n * n]; // [1,4,9,16]
Q40. [Medium] (Coding) Build a menu list that includes 'Admin' only when isAdmin is true.
Hint & Solution
Hint: Collection-if.
Solution:
var menu = ['Home', if (isAdmin) 'Admin'];
Q41. [Medium] (Theory) What's the difference between ... and ...??
Hint & Solution
Hint: Null operand.
Solution: ... spreads a collection's elements into a literal; ...? does the same but safely skips the operand when it's null (no crash).
Q42. [Medium] (Coding) Compute the intersection and union of {1,2,3} and {2,3,4}.
Hint & Solution
Hint: Set algebra methods.
Solution:
var a = {1,2,3}, b = {2,3,4};
a.intersection(b); // {2, 3}
a.union(b); // {1, 2, 3, 4}
Q43. [Medium] (Coding) From [1..10], build the even numbers only, using collection-for + collection-if together.
Hint & Solution
Hint: Nest if inside for.
Solution:
var nums = [for (var i = 1; i <= 10; i++) i];
var evens = [for (final n in nums) if (n.isEven) n]; // [2,4,6,8,10]
Q44. [Medium] (Theory) Do map and where return Lists? What do you do if you need a List?
Hint & Solution
Hint: Laziness.
Solution: No — they return lazy Iterables. Call .toList() (or .toSet()) to materialize a concrete collection.
Q45. [Medium] (Coding) Sum a list of ints two different ways.
Hint & Solution
Hint: fold and reduce.
Solution:
var nums = [1,2,3,4];
nums.fold(0, (s, n) => s + n); // 10 (works on empty list too)
nums.reduce((a, b) => a + b); // 10 (throws on empty list)
Q46. [Medium] (Coding) Iterate a map printing key → value for each entry.
Hint & Solution
Hint: .entries or forEach.
Solution:
for (final e in ages.entries) {
print('${e.key} → ${e.value}');
}
// or: ages.forEach((k, v) => print('$k → $v'));
Q47. [Advanced] (Coding) Group ['apple','avocado','banana','cherry'] into a Map<String, List<String>> by first letter.
Hint & Solution
Hint: putIfAbsent to create the list lazily.
Solution:
var words = ['apple','avocado','banana','cherry'];
var grouped = <String, List<String>>{};
for (final w in words) {
grouped.putIfAbsent(w[0], () => []).add(w);
}
// {a: [apple, avocado], b: [banana], c: [cherry]}
Q48. [Advanced] (Theory) Why can't you add to a const list, and when is a const collection useful?
Hint & Solution
Hint: Deeply immutable.
Solution: A const collection is frozen at compile time — its contents can't be added to, removed, or changed (add throws). Useful for fixed lookup tables you want to guarantee nobody mutates.
Q49. [Advanced] (Coding) Invert a Map<String, int> into a Map<int, String>.
Hint & Solution
Hint: Swap each entry's key and value.
Solution:
var m = {'a': 1, 'b': 2};
var inverted = {for (final e in m.entries) e.value: e.key}; // {1: a, 2: b}
(Map collection-for! Assumes values are unique.)
Q50. [Advanced] (Coding) Given List<List<int>> nested, flatten it into a single list using spread.
Hint & Solution
Hint: Spread each sublist inside a collection-for.
Solution:
var flat = [for (final sub in nested) ...sub];
// or: nested.expand((e) => e).toList();
Q51. [Advanced] (Theory) Why is membership testing O(1) for a Set but O(n) for a List?
Hint & Solution
Hint: Hashing vs. scanning.
Solution: A Set (hash set) hashes the value to find its bucket directly — roughly constant time. A List.contains must scan element by element until it finds a match — linear time. For frequent "contains" checks, use a Set.
Q52. [Advanced] (Coding) Count word frequencies in 'a b a c b a' into a Map<String, int>.
Hint & Solution
Hint: Split, then accumulate with ??.
Solution:
var counts = <String, int>{};
for (final w in 'a b a c b a'.split(' ')) {
counts[w] = (counts[w] ?? 0) + 1;
}
// {a: 3, b: 2, c: 1}
Section D — Functions (Q53–70)
Q53. [Basic] (Coding) Rewrite int twice(int x) { return x * 2; } with arrow syntax.
Hint & Solution
Hint: Single expression → =>.
Solution:
int twice(int x) => x * 2;
Q54. [Basic] (Theory) Are positional parameters required by default?
Hint & Solution
Hint: No brackets means…
Solution: Yes — a plain positional parameter must be passed, in order. You make parameters optional with { } (named) or [ ] (optional positional).
Q55. [Basic] (Coding) Write greet with a named name parameter and call it.
Hint & Solution
Hint: { } around the param; pass by name.
Solution:
void greet({required String name}) => print('Hi $name');
greet(name: 'Asha');
Q56. [Basic] (Theory) When can you not use =>?
Hint & Solution
Hint: Expressions vs. statements.
Solution: When the body needs more than one expression — loops, if blocks, multiple statements. Those require the full { ... } body with return.
Q57. [Medium] (Theory) Difference between { } and [ ] parameters?
Hint & Solution
Hint: Named vs. optional-positional.
Solution: { } = named (passed by name, any order, optional unless required). [ ] = optional positional (passed by position, omittable from the end). You can't use both groups in one function.
Q58. [Medium] (Coding) Write connect with named host (default 'localhost') and port (default 8080).
Hint & Solution
Hint: Defaults after = inside { }.
Solution:
void connect({String host = 'localhost', int port = 8080}) =>
print('$host:$port');
connect(port: 3000); // localhost:3000
Q59. [Medium] (Coding) Redesign sendEmail('x@y.com', 'Hi', true, false) so the call self-documents.
Hint & Solution
Hint: Named + required.
Solution:
void sendEmail({
required String to,
required String subject,
bool html = false,
bool urgent = false,
}) {}
sendEmail(to: 'x@y.com', subject: 'Hi', html: true);
Q60. [Medium] (Coding) Store a function in a variable typed int Function(int) and call it.
Hint & Solution
Hint: Functions are first-class values.
Solution:
int square(int x) => x * x;
int Function(int) op = square;
print(op(5)); // 25
Q61. [Medium] (Coding) Pass an anonymous function to map to uppercase a list of strings.
Hint & Solution
Hint: (x) => ... inline.
Solution:
['a','b'].map((s) => s.toUpperCase()).toList(); // [A, B]
Q62. [Medium] (Theory) What's a tear-off? Give an example where one works and one where it can't.
Hint & Solution
Hint: The lambda must be exactly (x) => f(x).
Solution: A tear-off passes a named function directly: list.forEach(print) instead of forEach((x) => print(x)). It can't replace (s) => s.toUpperCase() because that calls an instance method on the element, not a standalone function of the element.
Q63. [Medium] (Coding) Write power(base, [exponent]) where exponent defaults to 2.
Hint & Solution
Hint: Optional positional [ ] with a default.
Solution:
int power(int base, [int exponent = 2]) {
var r = 1;
for (var i = 0; i < exponent; i++) r *= base;
return r;
}
power(5); // 25
power(2, 3); // 8
Q64. [Advanced] (Theory) What is a closure?
Hint & Solution
Hint: Functions that remember.
Solution: A function that captures variables from the scope where it was defined and keeps them alive after that scope returns — a way to hold private, persistent state without a class.
Q65. [Advanced] (Coding) Write makeCounter() returning a function that yields 1, 2, 3… on successive calls.
Hint & Solution
Hint: Capture a local count.
Solution:
int Function() makeCounter() {
int count = 0;
return () => ++count;
}
var c = makeCounter();
c(); // 1
c(); // 2
Q66. [Advanced] (Coding) Return both the min and max of a list using a record, then destructure.
Hint & Solution
Hint: (int, int) return + var (a, b) = ....
Solution:
(int, int) minMax(List<int> xs) {
var lo = xs.first, hi = xs.first;
for (final x in xs) { if (x < lo) lo = x; if (x > hi) hi = x; }
return (lo, hi);
}
var (low, high) = minMax([4,1,9]); // 1, 9
Q67. [Advanced] (Coding) Write applyTwice(f, x) that applies a function to a value twice (f(f(x))).
Hint & Solution
Hint: Take a function parameter, call it twice.
Solution:
T applyTwice<T>(T Function(T) f, T x) => f(f(x));
applyTwice((n) => n + 3, 10); // 16
Q68. [Advanced] (Coding) Two counters made from the same makeCounter() — are their counts shared or independent? Demonstrate.
Hint & Solution
Hint: Each call creates a fresh scope.
Solution:
var a = makeCounter();
var b = makeCounter();
a(); a(); // a → 1, 2
b(); // b → 1 (independent)
Each makeCounter() call captures its own count, so the counters don't interfere.
Q69. [Advanced] (Coding) Return a named record ({String name, int age}) and access its fields.
Hint & Solution
Hint: Named record fields.
Solution:
({String name, int age}) getUser() => (name: 'Ben', age: 25);
var u = getUser();
print(u.name); // Ben
print(u.age); // 25
Q70. [Advanced] (Theory) Why are named parameters the reason Flutter widget code is so readable?
Hint & Solution
Hint: Look at any widget constructor.
Solution: Widgets take many configuration arguments; passing them positionally would be a wall of mystery values. Named parameters (child:, padding:, color:) label each argument at the call site, making deeply nested widget trees self-documenting.
Section E — String Manipulation (Q71–84)
Q71. [Basic] (Theory) Are Dart strings mutable? What does that imply for "modifying" one?
Hint & Solution
Hint: Methods return something.
Solution: No — strings are immutable. Every method returns a new string; to "change" a variable you reassign it (s = s.toUpperCase()).
Q72. [Basic] (Coding) Trim and lowercase ' HELLO '.
Hint & Solution
Hint: Chain two methods.
Solution:
' HELLO '.trim().toLowerCase(); // 'hello'
Q73. [Basic] (Coding) Split 'a,b,c' on commas, then rejoin with ' | '.
Hint & Solution
Hint: split then join.
Solution:
'a,b,c'.split(',').join(' | '); // 'a | b | c'
Q74. [Basic] (Coding) Zero-pad the int 42 to width 5 → '00042'.
Hint & Solution
Hint: toString then padLeft.
Solution:
42.toString().padLeft(5, '0'); // '00042'
Q75. [Medium] (Coding) Extract the file extension from 'a.b.final.pdf'.
Hint & Solution
Hint: lastIndexOf('.') + substring.
Solution:
var f = 'a.b.final.pdf';
f.substring(f.lastIndexOf('.') + 1); // 'pdf'
Q76. [Medium] (Theory) Difference between replaceAll and replaceFirst?
Hint & Solution
Hint: How many matches.
Solution: replaceAll replaces every occurrence; replaceFirst only the first. Both are case-sensitive unless you pass a case-insensitive RegExp.
Q77. [Medium] (Coding) Reverse 'dart' to 'trad'.
Hint & Solution
Hint: split → reversed → join.
Solution:
'dart'.split('').reversed.join(); // 'trad'
(For emoji-safe reversing, use .characters instead of split('').)
Q78. [Medium] (Coding) Produce initials 'A.L.' from 'ada lovelace'.
Hint & Solution
Hint: split on space, take first letter of each.
Solution:
var n = 'ada lovelace';
'${n.split(' ').map((w) => w[0].toUpperCase()).join('.')}.'; // 'A.L.'
Q79. [Medium] (Coding) Count digits in 'a1b22c333' using a RegExp.
Hint & Solution
Hint: \d + allMatches. Raw string!
Solution:
RegExp(r'\d').allMatches('a1b22c333').length; // 6
Q80. [Medium] (Theory) Why must regex patterns be raw strings (r'...')?
Hint & Solution
Hint: Who interprets the backslash first?
Solution: Without r, Dart processes escape sequences (\d, \n) before the regex engine sees them, mangling the pattern. A raw string passes the backslashes through untouched.
Q81. [Advanced] (Coding) Mask an email: 'asha@x.com' → 'a***@x.com'.
Hint & Solution
Hint: Split at @, keep first char, repeat *.
Solution:
var e = 'asha@x.com';
var at = e.indexOf('@');
var local = e.substring(0, at);
'${local[0]}${'*' * (local.length - 1)}${e.substring(at)}'; // 'a***@x.com'
Q82. [Advanced] (Coding) Extract year/month/day from '2026-07-08' using capture groups.
Hint & Solution
Hint: Parenthesized groups + group(n).
Solution:
var m = RegExp(r'(\d{4})-(\d{2})-(\d{2})').firstMatch('2026-07-08');
m?.group(1); // 2026
m?.group(2); // 07
m?.group(3); // 08
firstMatch is nullable, hence ?..
Q83. [Advanced] (Theory) When should you use StringBuffer instead of +=?
Hint & Solution
Hint: Immutability cost in a loop.
Solution: When building a string across many iterations. Repeated += allocates a new string each time (O(n²)-ish); StringBuffer accumulates in a mutable buffer and produces the result once with toString().
Q84. [Advanced] (Coding) Build '0,1,2,...,99' efficiently with a StringBuffer.
Hint & Solution
Hint: write in a loop, separator between.
Solution:
var b = StringBuffer();
for (var i = 0; i < 100; i++) {
if (i > 0) b.write(',');
b.write(i);
}
b.toString();
Section F — Control Flow & Patterns (Q85–100)
Q85. [Basic] (Theory) Why can't you write if (someString) in Dart like in JavaScript?
Hint & Solution
Hint: No truthy/falsy.
Solution: Dart conditions require a real bool. There's no truthy/falsy coercion, so you must check explicitly (if (s.isNotEmpty)), which prevents a class of "why did that branch run?" bugs.
Q86. [Basic] (Coding) Convert if (n.isEven) s = 'even'; else s = 'odd'; to a ternary.
Hint & Solution
Hint: cond ? a : b.
Solution:
var s = n.isEven ? 'even' : 'odd';
Q87. [Basic] (Coding) Print 0–4 with a for loop, then the same with for-in over a list.
Hint & Solution
Hint: Two loop forms.
Solution:
for (var i = 0; i < 5; i++) print(i);
for (final i in [0,1,2,3,4]) print(i);
Q88. [Basic] (Theory) Does Dart's switch fall through to the next case if you forget break?
Hint & Solution
Hint: Famous C/Java footgun — absent here.
Solution: No. Each non-empty case automatically stops at its end; no break is needed and there's no accidental fallthrough.
Q89. [Medium] (Coding) Write a switch expression mapping HTTP codes 200/404/500 to messages, with a fallback.
Hint & Solution
Hint: Arrows, commas, _.
Solution:
String msg(int c) => switch (c) {
200 => 'OK',
404 => 'Not Found',
500 => 'Server Error',
_ => 'Unknown',
};
Q90. [Medium] (Coding) Classify an int as 'small' (1–3), 'medium' (4–9), or 'large' using logical-or and relational patterns.
Hint & Solution
Hint: || and >= && <.
Solution:
String f(int n) => switch (n) {
1 || 2 || 3 => 'small',
>= 4 && <= 9 => 'medium',
_ => 'large',
};
Q91. [Medium] (Coding) Destructure ('Asha', 30) into name and age in one line.
Hint & Solution
Hint: Record pattern in a declaration.
Solution:
var (name, age) = ('Asha', 30);
Q92. [Medium] (Coding) Swap two variables without a temporary, using a pattern.
Hint & Solution
Hint: Assign a record pattern.
Solution:
var (a, b) = (1, 2);
(a, b) = (b, a); // a == 2, b == 1
Q93. [Medium] (Coding) Use if-case to check that Object data is a [int x, int y] list and print the point.
Hint & Solution
Hint: List pattern + binding.
Solution:
if (data case [int x, int y]) {
print('($x, $y)');
}
Q94. [Medium] (Theory) What does a when guard add to a pattern?
Hint & Solution
Hint: Extra boolean test.
Solution: It adds a runtime condition; the arm matches only if the pattern matches and the when expression is true (e.g. case var a when a > 0).
Q95. [Advanced] (Coding) Write ticket(int age) returning 'child' (< 13), 'adult' (< 65), 'senior' otherwise, using a guarded switch expression.
Hint & Solution
Hint: var a when ....
Solution:
String ticket(int age) => switch (age) {
var a when a < 13 => 'child',
var a when a < 65 => 'adult',
_ => 'senior',
};
Q96. [Advanced] (Coding) Match a Point(x, y) object: report if it's on the X axis, Y axis, or elsewhere.
Hint & Solution
Hint: Object pattern with field matching.
Solution:
switch (p) {
case Point(x: 0, y: var y): print('Y axis at $y');
case Point(x: var x, y: 0): print('X axis at $x');
default: print('elsewhere');
}
Q97. [Advanced] (Theory) What is exhaustiveness checking, and which types benefit most?
Hint & Solution
Hint: Finite, known set of values.
Solution: A switch over a finite type (enum or sealed class) must cover every case or it won't compile. Adding a new variant turns every unhandled switch into a compile error — a guaranteed refactor checklist.
Q98. [Advanced] (Coding) Write an exhaustive switch expression over enum Light { red, yellow, green } with no default.
Hint & Solution
Hint: Cover all three → no default needed.
Solution:
String act(Light l) => switch (l) {
Light.red => 'Stop',
Light.yellow => 'Slow',
Light.green => 'Go',
};
Adding Light.flashing later makes this a compile error until handled.
Q99. [Advanced] (Coding) Parse a ['move', int n] or ['rotate', int deg] command list with switch patterns; ignore anything else.
Hint & Solution
Hint: List patterns with a literal first element + binding.
Solution:
String run(List cmd) => switch (cmd) {
['move', int n] => 'move $n',
['rotate', int deg] => 'rotate $deg',
_ => 'ignored',
};
run(['move', 5]); // 'move 5'
Q100. [Advanced] (Theory) Pull it together: name three Dart 3 features from this series that, combined, let you safely handle decoded JSON without a single if (x != null) ladder.
Hint & Solution
Hint: Patterns, null safety, types.
Solution: (1) if-case / switch patterns to test shape and destructure in one step; (2) typed patterns (int x, String s) that check the type and bind safely — no as; (3) sound null safety so any missing field is a ? type you must handle. Together they replace nested null/type checks with a single declarative match — e.g. if (json case {'name': String name, 'age': int age}) { ... }.
You made it 🎉
That's the entire Dart Fundamentals series — from your first program to pattern matching and a 100-question gauntlet. If you can answer all 100 explaining the why, not just the what, you genuinely know Dart's core.
Where to go next:
- Apply it: the Object-Oriented Dart series builds real types — classes, mixins, sealed classes — on top of these fundamentals.
- Build something: open DartPad and write a small CLI, or jump into Flutter where every one of these features earns its keep.
Bookmark this bank and re-run the questions you needed help with in a week. Spaced repetition is how fundamentals become instinct. Happy coding!