Question

The situation:

I create visual components from a TDataSet that should keep an id as a reference. The component can only store objects, not strings.

Pseudo code:

for Record in DataSet do
  AddComponent.Data := Record['id']

Where Data is of type TObject and the id field is of a string type (actually a GUID).

The question:

How do I store a string in the object property?

I have tried a boxing solution that uses a custom type TBox<string>, but I want to avoid memory management issues.

Was it helpful?

Solution

If the type of Data is TObject then you cannot avoid memory management issues. The compiler is not going to manage the lifetime of a TObject instance for you. You will have to use one of the standard lifetime management mechanisms:

  1. You take care of it with try/finally blocks, and explicit calls to Free.
  2. You derive your object from TComponent and let it be owned by something that is guaranteed to outlive all references to your wrapped string.

Option 2 has a number of variants. Other ways to hand off ownership include using interfaces. So long as the owner outlives all references to the object then you are safe.

Personally I don't very much like option 2. If the compiler isn't going to manage the lifetime of my objects, I prefer to manage it myself. I find that if I use explicit management then it is easier to reason about when my objects' lives end.

OTHER TIPS

How do I store a string in the object property?

Why ?

Well,

  1. sizeof(TObject) = sizeof(Pointer)
  2. String is ref-counted type, so you'd either use StringRec cracker type and manage all the intrinsics, or use the compielr build-in counter. I'd try th second approach, despite it being less effectve and adding extra indirection level.

.

type StringContainer = record Data: String; end;
     PStringContainer = ^StringContainer;

var p: PStringContainer;

for Record in DataSet do begin
  New(P);
  P^.Data := Record['id'];
  Pointer(AddComponent.Data) := P;
end;

Don't forget to call Dispose(...) when you'll no more need those pointers in the component.

procedure TMyComponent.BeforeDestruction;
var P: PStringContainer;
begin
    P := Pointer(Data);
    Data := nil;
    Dispose(P); // should free the string, since P type was given
    inherited; 
end;

I want to avoid memory management issues.

Which kind of issues exactly and in which part of the program ?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top