Skip to main content
The cascade notation (..) allows for the execution of a sequence of operations on the same object instance. It evaluates an expression, performs a property access or method invocation on the result, discards the return value of that invocation, and returns the original object reference.

Syntax

The cascade operator follows the object expression and precedes the member invocation.
receiver
  ..member1()
  ..member2 = value
  ..member3();

Operational Semantics

The fundamental distinction between the dot operator (.) and the cascade operator (..) lies in the return value of the expression.
  • Dot Operator (.): Returns the result of the method call or property access.
  • Cascade Operator (..): Discards the result of the method call or property access and returns the receiver (the object to the left of the operator).
Given a class Builder with a method setValue() that returns void:
class Builder {
  int value = 0;
  void setValue(int v) {
    value = v;
  }
}

void main() {
  var builder = Builder();

  // Standard invocation
  // Returns 'void' because setValue returns void.
  // var result = builder.setValue(10); 

  // Cascade invocation
  // Returns the 'builder' instance, not 'void'.
  var sameBuilder = builder..setValue(10); 
  
  assert(builder == sameBuilder); // True
}

Desugaring

The compiler treats a cascade sequence as a temporary variable assignment to ensure the receiver is evaluated only once. The expression:
final obj = Target()..methodA()..methodB();
Is semantically equivalent to:
final temp = Target();
temp.methodA();
temp.methodB();
final obj = temp;

Null-Shorting Cascade (?..)

The null-shorting cascade operator (?..) allows cascades to be performed on nullable receivers. If the receiver evaluates to null, the entire cascade expression short-circuits and evaluates to null. If the receiver is non-null, the cascade proceeds as a standard .. operation.
Target? target = null;

// Evaluates to null immediately; methodA is not called.
target?..methodA()..methodB(); 
Note: The ?.. operator is only required for the first operation in the sequence. Subsequent operations in the same chain use the standard .. operator, as the null check has already occurred.

Nesting

Cascades can be nested, though this relies heavily on indentation for readability. The cascade captures the most immediate receiver in the syntactic scope.
final sb = StringBuffer()
  ..write('Level 1')
  ..write(StringBuffer()
    ..write('Level 2') // Cascades on the inner StringBuffer
    ..write('End Level 2'))
  ..write('End Level 1'); // Cascades on the outer 'sb'
Master Dart with Deep Grasping Methodology!Learn More