Existem dois tipos de sintaxe em cascata: .. e ?..
Executar várias atribuições de propriedades e chamadas de método consecutivas no mesmo objeto, elimina variáveis temporais e deixa o código mais fluido e coeso.
A sintaxe em cascata não é um operador, é um açúcar sintático exclusivo do Dart.
1. Cascata comum ..
Usar quando tiver certeza que o objeto nunca é null
Todas as operações com .. agem sobre o objeto original do início, ignorando os valores retornados por cada método intermediário.
Exemplo oficial
import 'dart:ui';
void main() {
// Escrita em cascata
var paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 5.0;
// Forma dividida equivalente (sem cascata, repetir nome da variável)
var paint2 = Paint();
paint2.color = Colors.black;
paint2.strokeCap = StrokeCap.round;
paint2.strokeWidth = 5.0;
}Code language: JavaScript (javascript)
Esse exemplo importa a biblioteca dart:ui exclusiva do Flutter, só funcionando em projetos Flutter. Como esse guia fala de Dart puro, basta entender a sintaxe mostrada acima. O próximo exemplo usa uma classe nativa padrão do Dart: StringBuffer.
Classe para manipulação de strings: StringBuffer
void main() {
// Sintaxe em cascata
var sb = StringBuffer()
..write("Hello ")
..write("FoxDevelop.com ")
..writeln("Cascade");
print(sb.toString());
// Versão equivalente sem cascata
var sb2 = StringBuffer();
sb2.write("Hello ");
sb2.write("FoxDevelop.com ");
sb2.writeln("Cascade");
print(sb2.toString());
}Code language: PHP (php)
Resultado da execução
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
Hello FoxDevelop.com Cascade
Hello FoxDevelop.com CascadeCode language: CSS (css)
A sintaxe acima é usada quando você tem garantia que objetos como paint, sb e sb2 nunca valem null: permite atribuir valores rapidamente sem repetir o nome do objeto. Por outro lado, se o objeto for null, um erro aparece imediatamente.
void main() {
var sb = null
..write("Hello ")
..write("FoxDevelop.com ")
..writeln("Cascade");
print(sb.toString());
}Code language: JavaScript (javascript)

Para resolver esse problema, existe a segunda forma de uso mostrada abaixo.
2. Cascata segura para null ?..
Se o objeto for null, toda a cadeia de cascata não será executada, evitando erros de ponteiro nulo. Apenas o primeiro elo usa ?..; os seguintes usam diretamente ...
void main() {
var sb = null
?..write("Hello ")
..write("FoxDevelop.com ")
..writeln("Cascade");
print(sb.toString());
}Code language: Dart (dart)
Repare no ponto de interrogação antes de ?..write(“Hello “)
Ao compilar novamente, o código roda normalmente
D:\dartdemo\firstdart>dart run
Building package executable...
Built firstdart:firstdart.
nullCode language: CSS (css)
Não ocorre nenhum erro
Abaixo o exemplo oficial: basta entender a estrutura sintática.
// Comece com ?.., depois use apenas ..
document.querySelector('#confirm')
?..textContent = 'Confirm'
..classList.add('important')
..onClick.listen((e) => window.alert('Confirmed!'))
..scrollIntoView();
// Forma dividida segura para null equivalente
final button = document.querySelector('#confirm');
button?.textContent = 'Confirm';
button?.classList.add('important');
button?.onClick.listen((e) => window.alert('Confirmed!'));
button?.scrollIntoView();Code language: JavaScript (javascript)
Cascata aninhada
final addressBook = (AddressBookBuilder()
..name = 'jenny'
..email = 'jenny@example.com'
// Cascata separada para o objeto interno PhoneNumberBuilder
..phone = (PhoneNumberBuilder()
..number = '415-555-0100'
..label = 'home')
.build())
.build();Code language: PHP (php)
O atributo phone é um objeto instanciado via PhoneNumberBuilder() com valores atribuídos.
Observações importantes
A sintaxe em cascata só funciona com instâncias de objeto; se colocada após um método que retorna void, ocorre erro de compilação.
var sb = StringBuffer();
sb.write('foo') // write retorna void
..write('bar'); // Erro: o tipo void não tem o método writeCode language: Dart (dart)
Aqui criamos primeiro um objeto StringBuffer chamado sb
Mas a linha termina com ponto e vírgula antes de chamar write no sb; como write retorna void, não é possível encadear outro ..write depois, a menos que o método write retorne uma instância de objeto.
Forma correta de escrita
var sb = StringBuffer()
..write('foo')
..write('bar');Code language: Dart (dart)
Resumo
..retorna sempre ao objeto raiz original em cada operação, ignorando os valores retornados pelos métodos. Funciona similar ao encadeamento de métodos de outras linguagens como JavaScript.?..é a cascata segura para null, evitando erros quando o objeto é null. Só é usado no início da cadeia: se a primeira operação rodar, o objeto não é null, então os próximos elos não precisam de ?..- Suporta cascatas aninhadas
- Não se pode adicionar cascata após um método com retorno
void ..não é um operador, mas sim um açúcar sintático do Dart
O que é açúcar sintático?
Açúcar sintático é uma abreviação leve oferecida por linguagens de programação para uma mesma lógica base durante a análise sintática; não adiciona novas funcionalidades à linguagem. O compilador ou interpretador converte automaticamente essa sintaxe curta para o código padrão equivalente antes de gerar código intermediário.