Italian community of Lazarus and Free Pascal

Programmazione => Generale => Topic aperto da: AndreaM - Novembre 29, 2016, 06:40:15 pm

Titolo: Oggetto restituito da una funzione
Inserito da: AndreaM - Novembre 29, 2016, 06:40:15 pm
Buonasera,
Nel caso io avessi una funzione che restituisce un oggetto come ad esempio:
Codice: [Seleziona]
Function Elenco:TstringList;
begin
 Result:=TStringList.Create;
 Result.Add('Prova');
 // e via dicendo...
 // fà altre cose...
end;
Si può chiamare la funzione con un assegnamento del tipo:
Codice: [Seleziona]
try
  MyLista:=Elenco;
Finally
  MyLista.Free
end;
Ma nulla vieta di chiamare anche semplicemente
Codice: [Seleziona]
Elenco;
In questo caso però non è stato chiamato il distruttore e quindi si ha perdita di memoria!
La domanda è:
C'è la possibilità dall'interno della funzione stessa (alla fine) di verificare se è stata assegnata e nel caso contrario procedere alla liberazione di memoria con ad esempio una cosa del tipo:
Codice: [Seleziona]
If not assigned(Result) then 
  Result.free;
Grazie a tutti!
Titolo: Re:Oggetto restituito da una funzione
Inserito da: nomorelogic - Novembre 30, 2016, 08:45:39 am
Ma nulla vieta di chiamare anche semplicemente
Codice: [Seleziona]
Elenco;
In questo caso però non è stato chiamato il distruttore e quindi si ha perdita di memoria!

In effetti in questi casi è meglio dare dei nomi più significativi a queste funzioni.
Se istanziano un oggetto in memoria e non si occupano di liberarlo, un nome più adatto potrebbe essere:
Codice: [Seleziona]
CreaElenco;

Non cambia assolutamente nulla chiaramente, ma già ti da un indizio sul fatto che devi verificare chi libererà la cosa creata.

Una alternativa è evitare che una funzione istanzi risorse se poi non è possibile essere sicuri che all'uscita queste risorse saranno liberate.
L'approccio è quello di lasciare che sia il chiamante a preoccuparsi della vita degli oggetti e fare una procedura tipo:
Codice: [Seleziona]
procedure PopolaElenco(sl: TStrings);
begin
   sl.Clear;
   sl.Add('...');
   sl.Add('...');
   sl.Add('...');
end;

in questo modo sarà il chiamante a dover fornire un oggetto esistente che verrà poi popolato.


Edit:
Il messaggio di fondo è che è meglio associare un verbo al sostantivo quando si da un nome alle procedure/funzioni.
Personalmente preferisco di gran lunga l'approccio 'PopolaElenco' in quanto sgancia totalmente la funzione dal contesto in cui verrà utilizzata.