Il costrutto case di Object Pascal funziona solo su tipi ordinali (interi, caratteri, enumerazioni): non accetta direttamente una string. Il risultato è che confrontare una stringa con più valori possibili finisce spesso in una catena di if..else if, meno leggibile e più scomoda da estendere di un vero case. System.StrUtils offre un modo elegante per aggirare il problema.
Il problema: una catena di if
Il codice che si vuole evitare è questo, ripetuto magari per una decina di valori possibili:
if Tipo = 'E' then
Result := 'Entrata'
else if Tipo = 'U' then
Result := 'Uscita'
else if Tipo = 'R' then
Result := 'Rimborso'
else
Result := 'Sconosciuto';La soluzione: AnsiIndexStr
AnsiIndexStr(const AText: string; const AValues: array of string): Integer restituisce la posizione (0-based) di AText all'interno dell'array AValues, oppure -1 se non trova corrispondenza. Passando quel risultato a un case, si ottiene l'equivalente di uno switch su stringhe:
uses
System.StrUtils;
function TipoRigaEsteso(const Tipo: string): string;
begin
case AnsiIndexStr(Tipo, ['E', 'U', 'R']) of
0: Result := 'Entrata';
1: Result := 'Uscita';
2: Result := 'Rimborso';
else
Result := 'Sconosciuto'; // AnsiIndexStr ha restituito -1: nessuna corrispondenza
end;
end;Il confronto è case-sensitive e usa la codifica locale ("Ansi", nel nome storico della funzione): 'e' minuscolo non corrisponderebbe a 'E'. Se serve un confronto insensibile a maiuscole/minuscole, la variante da usare è AnsiIndexText, con la stessa identica firma.
Perché è meglio della catena di if
Il vantaggio non è solo estetico. Con l'array esplicito, aggiungere un nuovo valore da riconoscere significa aggiungere una voce all'array AValues e un nuovo ramo al case, in due punti vicini e paralleli: è più difficile dimenticare di gestire un caso, cosa che invece capita più facilmente in una catena di if..else if lunga, dove un nuovo ramo va inserito nel posto giusto tra gli altri.
Quando basta un booleano: MatchStr
Se l'obiettivo non è ramificare su più valori ma solo verificare se una stringa corrisponde a uno tra diversi valori ammessi (senza bisogno di sapere quale), MatchStr — sempre in System.StrUtils — è più diretta di un AnsiIndexStr(...) >= 0:
if MatchStr(Tipo, ['E', 'U', 'R']) then
// Tipo è uno dei tre valori ammessi
else
// Tipo non è riconosciutoTra le due, la scelta dipende da cosa serve dopo il controllo: AnsiIndexStr quando il codice successivo deve comportarsi diversamente per ciascun valore, MatchStr quando basta sapere sì/no se il valore è tra quelli ammessi.