← Back to blog
Dart Fundamentals · Part 10 of 10
July 8, 202627 min read

100 Questions to Master Dart Fundamentals (with Hints & Solutions)

DartFlutter

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 intx.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!