Skip to main content
The ?. operator, formally known as the null-aware access operator or conditional member access operator, provides a safe mechanism to access properties or invoke methods on an expression that may evaluate to null. It evaluates the left-hand operand; if the operand is null, the operation short-circuits and yields null without throwing a NoSuchMethodError. If the operand is non-null, it proceeds with standard member access or invocation. Syntax
expression?.member
Evaluation Mechanics
  1. The runtime evaluates expression.
  2. If expression == null, the entire expression expression?.member immediately evaluates to null. If member is a property of type T or a method returning type T, the static type of the resulting expression is T?. Exception: If member is a method that returns void, the static type of the expression remains void, not void?.
  3. If expression != null, the runtime accesses or invokes member on the resolved object.
Code Visualization Property Access:
String? text = null;

// Evaluates to null. 
// Semantically equivalent to: text == null ? null : text.length
int? length = text?.length; 
Method Invocation:
List<int>? numbers = null;

// Evaluates to null. The add() method is never executed.
// The static type of this expression is void.
numbers?.add(1); 
Short-Circuit Chaining When multiple ?. operators are chained, the evaluation halts at the exact point the first null is encountered. Subsequent property accesses or method invocations in the chain are completely bypassed.
class C {
  int value = 42;
}

class B {
  C? c;
}

class A {
  B? b;
}

A? a = A();

// 'a' is non-null, but 'a.b' is null. 
// The chain short-circuits at 'a?.b', returning null.
// The accesses for 'c' and 'value' are never attempted.
int? result = a?.b?.c?.value; 
Interaction with Standard Access (.) Dart employs “null-aware shorting.” If a null-aware operator short-circuits an expression chain, any subsequent standard dot operators (.) within that continuous chain are also bypassed at runtime. However, the expression must still satisfy Dart’s static compile-time null safety checks. The ?. operator only handles the potential nullability of the operand immediately preceding it. Subsequent standard accesses (.) are only permitted by the compiler if the preceding properties are statically known to be non-nullable.
class Bar {
  int c = 42;
}

class Foo {
  Bar b = Bar(); // Statically non-nullable
}

Foo? obj = null;

// Valid syntax. The chain short-circuits at 'obj?.'.
// The standard '.' before 'c' is never evaluated at runtime.
// This compiles strictly because 'b' is declared as non-nullable in 'Foo'.
int? val = obj?.b.c; 
Tired of Poor Dart Skills? Fix That With Deep Grasping!Learn More