🎓 A1Learner
🔍
0 of 37 lessons completed

Dart Null-Aware In Depth

Null-aware operators in depth combine assignment, indexing, and chained reads that stay safe on null. Each operator skips its work when the value it touches holds null.

Assign only when null

name starts with no value, so the first ??= stores Guest. The second ??= finds a value in place and changes nothing.

void main() {
  String? name;
  name ??= 'Guest';
  print(name);
  name ??= 'Ana';
  print(name);
}

The null-aware index

The filled list gives its first element and its length. The empty variable gives null for both reads instead of stopping the program.

void main() {
  List<int>? nums = [7, 8, 9];
  print(nums?[0]);
  print(nums?.length);
  List<int>? empty;
  print(empty?[0]);
  print(empty?.length);
}

A safe chain across objects

Each read in the chain runs only when the value before it is present. A null link anywhere makes the whole chain give null.

class Address {
  String? city;

  Address(this.city);
}

class Person {
  Address? address;

  Person(this.address);
}

void main() {
  var ana = Person(Address('York'));
  var bob = Person(null);
  Person? nobody;
  print(ana.address?.city);
  print(bob.address?.city);
  print(nobody?.address?.city);
}

A method call on a nullable value

The method is called directly on a parameter that might hold null. The compiler refuses the program and prints this error.

void shout(String? name) {
  print(name.toUpperCase());
}

void main() {
  shout('ana');
}

The safe version of the same call

The safe call runs the method only when name holds a value. The text call prints in capitals and the null call prints null.

void shout(String? name) {
  print(name?.toUpperCase());
}

void main() {
  shout('ana');
  shout(null);
}

Example

class Box {
  List<int>? items;

  Box(this.items);
}

void main() {
  var box = Box(null);
  box.items ??= [4, 5];
  print(box.items?[0]);
  print(box.items?.length);
}

Key points

  • The ??= operator assigns a value only when the variable currently holds null.
  • A second ??= on a filled variable leaves the stored value unchanged.
  • The null-aware index reads an element only when the list is not null, and gives null otherwise.
  • A chain of safe reads gives null as soon as one link holds null, and the rest of the chain is skipped.
  • Calling a method directly on a nullable value is a compile error, because the call might land on null.

In this example, the box starts with a null items field. The ??= line fills it with a two element list because it holds null. The null-aware index then shows the first element 4, and the safe length read shows 2.

Note

These operators keep null handling inside the expression, with no extra if statement.

Try it Yourself

Edit the code, then press Run.

Running is simulated · DartPad

Exercise

What does name ??= 'Guest' do when name already holds Ana?