Wrapping TStringList in un record
-
06-07-2019 - |
Domanda
Tendo a usare TStringList di Delphi per la manipolazione del testo, quindi scrivo molte procedure / funzioni come:
var
TempList: TStringList;
begin
TempList:= TStringList.Create;
try
// blah blah blah do stuff with TempList
finally
TempList.Free;
end;
end;
Sarebbe bello tagliare la creazione e la liberazione per una classe di utilità così comune.
Poiché ora abbiamo record con metodi, è possibile racchiudere una classe come TStringList in a Registra in modo da poter avere:
var
TempList: TRecordStringList;
begin
// blah blah blah do stuff with TempList
end;
Soluzione
È possibile. Crea un'interfaccia che esponga i metodi / oggetti che desideri:
type
IStringList = interface
procedure Add(const s: string); // etc.
property StringList: TStringList read GetStringList; // etc.
end;
Implementa l'interfaccia e falla avvolgere un vero TStringList
:
type
TStringListImpl = class(TInterfacedObject, IStringList)
private
FStringList: TStringList; // create in constructor, destroy in destructor
// implementation etc.
end;
Quindi implementare il record:
type
TStringListRecord = record
private
FImpl: IStringList;
function GetImpl: IStringList; // creates TStringListImpl if FImpl is nil
// returns value of FImpl otherwise
public
procedure Add(const s: string); // forward to GetImpl.Add
property StringList: TStringList read GetStringList; // forward to
// GetImpl.StringList
// etc.
end;
Il fatto che all'interno del record sia presente un'interfaccia significa che il compilatore gestirà automaticamente il conteggio dei riferimenti, chiamando _AddRef e _Release man mano che le copie vengono create e distrutte, quindi la gestione della durata è automatica. Funziona con oggetti che non conterranno mai un riferimento a se stessi (creazione di un ciclo): il conteggio dei riferimenti richiede vari trucchi per superare i cicli nel grafico di riferimento.
Altri suggerimenti
Se sei abbastanza fortunato da aver effettuato l'upgrade a Delphi 2009, dai un'occhiata a Il lavoro di Barry con puntatori intelligenti .
TSmartPointer<T: class> = record
strict private
FValue: T;
FLifetime: IInterface;
public
constructor Create(const AValue: T); overload;
class operator Implicit(const AValue: T): TSmartPointer<T>;
property Value: T read FValue;
end;
Sono davvero fantastici, ma richiedono metodi generici e anonimi. Se non hai eseguito l'upgrade a Delphi 2009 , fallo ora! Soprattutto mentre offrono il loro speciale BOGO . Ottieni anche il Manuale per gli sviluppatori Delphi di Marco gratuito solo per download della versione di prova . Ne ho già acquistato una copia.
Esiste già un altro esempio implementato in CC .
StringList è uguale a TStringList, tranne per il fatto che è un valore genere. Non deve essere creato, distrutto o messo dentro try / finally. Questo viene fatto dal compilatore per te. Ci sono praticamente nessuna penalità speciale per le prestazioni perché funzioni:
var strings: StringList; astr: string; begin strings.Add('test1'); strings.Add('test2'); aStr := string(strings); RichEdit.Lines.AddStrings(strings); end;
Il codice può essere utilizzato come modello per racchiudere qualsiasi oggetto TO come tipo di classe valore.
Ha già tutto per una TStringList esposta per te.