Envolviendo TStringList en un registro
-
06-07-2019 - |
Pregunta
Tiendo a usar TStringList de Delphi para la manipulación de texto, así que escribo muchos procedimientos / funciones como:
var
TempList: TStringList;
begin
TempList:= TStringList.Create;
try
// blah blah blah do stuff with TempList
finally
TempList.Free;
end;
end;
Sería bueno cortar la creación y la liberación de una clase de utilidad tan común.
Dado que ahora tenemos registros con métodos, ¿es posible ajustar una clase como TStringList en un Grabar para poder tener:
var
TempList: TRecordStringList;
begin
// blah blah blah do stuff with TempList
end;
Solución
Es posible. Cree una interfaz que exponga los métodos / objetos que desee:
type
IStringList = interface
procedure Add(const s: string); // etc.
property StringList: TStringList read GetStringList; // etc.
end;
Implemente la interfaz y haga que ajuste una TStringList
real:
type
TStringListImpl = class(TInterfacedObject, IStringList)
private
FStringList: TStringList; // create in constructor, destroy in destructor
// implementation etc.
end;
Luego implemente el registro:
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;
El hecho de que haya una interfaz dentro del registro significa que el compilador manejará el recuento de referencias automáticamente, llamando a _AddRef y _Release a medida que las copias se crean y destruyen, por lo que la administración de por vida es automática. Esto funciona para objetos que nunca contendrán una referencia a sí mismos (creando un ciclo): el recuento de referencias necesita varios trucos para superar los ciclos en el gráfico de referencia.
Otros consejos
Si tiene la suerte de haberse actualizado a Delphi 2009, consulte El trabajo de Barry con punteros inteligentes .
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;
Son geniales, pero requieren métodos genéricos y anónimos. Si no ha actualizado a Delphi 2009 , ¡hágalo ahora! Especialmente mientras ofrecen su BOGO special . También obtienes el Manual para desarrolladores de Delphi gratis de Marco solo por descargando la versión de prueba . Ya compré una copia también.
Ya hay otro ejemplo implementado en CC .
StringList es lo mismo que TStringList excepto que es un valor tipo. No tiene que ser creado, destruido o puesto dentro intentar / finalmente. El compilador lo hace por usted. Existen prácticamente no hay sanciones especiales de rendimiento para que estas funcionen:
var strings: StringList; astr: string; begin strings.Add('test1'); strings.Add('test2'); aStr := string(strings); RichEdit.Lines.AddStrings(strings); end;
El código se puede usar como plantilla para ajustar cualquier TObject como un tipo de clase de valor.
Ya tiene todo para una TStringList expuesta para usted.