switch în Dart

Alege un bloc de cod după valoarea sau forma unei expresii; în Dart 3 fiecare case este un pattern.

Sintaxă
switch (valoare) {
  case Pattern1:
    ...
  case Pattern2 || Pattern3:
    ...
  case Pattern4 when conditie:
    ...
  default:   // sau case _:
    ...
}

Ce face switch

Instrucțiunea switch compară o valoare cu fiecare case, de sus în jos, și execută blocul primului case care se potrivește. Din Dart 3 nu mai este nevoie de break la final: după blocul unui case, execuția iese din switch. Mai multe case-uri goale la rând împart același bloc.

Fiecare case este un pattern: o constantă (case 'luni':), un interval relațional (case >= 9:), o alternativă (case 'sâmbătă' || 'duminică':), un tip cu variabilă (case int n:), un record sau o listă (case [var primul, ...]:). Variabilele din pattern se pot folosi în blocul acelui case.

default: (sau case _:) prinde orice valoare rămasă. Pe un enum sau pe o clasă sealed, analizorul verifică dacă ai tratat toate cazurile.

Exemple

Exemplul 1: Constante și case-uri grupate

'sâmbătă' || 'duminică' tratează două valori în același case. Nu e nevoie de break.

void program(String zi) {
  switch (zi) {
    case 'sâmbătă' || 'duminică':
      print('$zi: liber');
    case 'vineri':
      print('$zi: program scurt, 8-14');
    default:
      print('$zi: program normal, 8-16');
  }
}

void main() {
  for (final zi in ['luni', 'vineri', 'duminică']) {
    program(zi);
  }
}

Rezultat

luni: program normal, 8-16
vineri: program scurt, 8-14
duminică: liber

Exemplul 2: Pattern-uri relaționale

>= 9 și >= 5 && < 7 sunt pattern-uri care compară valoarea.

void main() {
  for (final nota in [10, 8, 6, 2]) {
    switch (nota) {
      case >= 9:
        print('$nota: excelent');
      case >= 7:
        print('$nota: bine');
      case >= 5 && < 7:
        print('$nota: suficient');
      default:
        print('$nota: corigent');
    }
  }
}

Rezultat

10: excelent
8: bine
6: suficient
2: corigent

Exemplul 3: Pattern-uri pe tip și pe listă

case int n verifică tipul și leagă valoarea; [var primul, ...] se potrivește cu o listă nevidă.

void analizeaza(Object? date) {
  switch (date) {
    case null:
      print('lipsă');
    case int n when n < 0:
      print('număr negativ: $n');
    case int n:
      print('număr: $n');
    case [var primul, ...]:
      print('listă care începe cu $primul');
    case String s:
      print('text: $s');
    default:
      print('alt tip: ${date.runtimeType}');
  }
}

void main() {
  for (final d in [null, -3, 42, ['Ana', 'Ion'], 'Sibiu', 2.5]) {
    analizeaza(d);
  }
}

Rezultat

lipsă
număr negativ: -3
număr: 42
listă care începe cu Ana
text: Sibiu
alt tip: double

Greșeli frecvente

  • case gol urmat de alt case înseamnă că împart blocul; dacă vrei un bloc gol care nu face nimic, scrie un comentariu și o instrucțiune goală sau break;.
  • Ordinea contează: un case int n: pus înaintea lui case int n when n < 0: îl face pe al doilea inutil (analizorul avertizează).
  • Pentru a calcula o valoare, expresia switch (final x = switch (v) { ... };) este mai scurtă decât instrucțiunea.

Comenzi înrudite

  • expresii switch: Forma de switch care produce o valoare: fiecare ramură este pattern => expresie.
  • when (guard): Adaugă o condiție suplimentară la un pattern din switch sau if-case; cazul se alege doar dacă e adevărată.
  • pattern-uri (destructurare): Desfac o valoare (record, listă, map, obiect) în variabile separate, într-o singură declarație.
  • sealed: Clasă cu un set închis de subtipuri, toate în același fișier; switch-ul pe ea verifică dacă ai tratat toate cazurile.
  • enum: Un tip cu un număr fix de valori numite (zilele săptămânii, stările unei comenzi), eventual cu câmpuri și metode.