Reputation: 2593
I have an ObjectList that is populated. Then details changed in the objects. Now I need to free the ObjectList but when I do it also frees the objects in the list. How can I free this list without freeing the objects themselfs?
Example code:
{Gets starting cards and put them into the correct rows}
//***************************************************************************
procedure TFGame.GetStartingCards;
//***************************************************************************
const
ManaTypes : array [0..3] of string = ('Lava','Water','Dark','Nature');
var
i: integer;
z:integer;
Cards: TObjectList<Tcard>;
begin
Cards := TObjectList<TCard>.Create;
z:=0;
{add all tcards (Desgin ) to this list in order Lava,water,dark,nature }
cards.Add(cardLava1);
cards.Add(cardlava2);
cards.Add(cardlava3);
cards.Add(cardlava4);
cards.Add(cardwater1);
cards.Add(cardwater2);
cards.Add(cardwater3);
cards.Add(cardwater4);
cards.Add(carddark1);
cards.Add(carddark2);
cards.Add(carddark3);
cards.Add(carddark4);
cards.Add(cardnature1);
cards.Add(cardnature2);
cards.Add(cardnature3);
cards.Add(cardnature4);
//get data from DB
for i := 0 to Length(ManaTypes) - 1 do
begin
with adoquery1 do
begin
close;
sql.Clear;
sql.Add('SELECT TOP 4 * FROM Cards WHERE Color = "'+ManaTypes[i]+'" ORDER BY Rnd(-(1000*ID)*Time())');
open;
end;
{return the result of everything for giving mana type.. }
if adoquery1.RecordCount = 0 then
Showmessage('Error no cards in db');
adoquery1.First;
while not adoquery1.Eof do
begin
cards[z].Cname := adoquery1.FieldByName('Name').AsString;
cards[z].Ccost := adoquery1.Fieldbyname('Cost').AsInteger;
cards[z].Ctext := adoquery1.FieldByName('Text').AsString;
cards[z].Ccolor := adoquery1.FieldByName('Color').AsString;
cards[z].Cinplay := false; //in the play area
if adoquery1.fieldbyname('Power').asstring <> '' then
cards[z].Cpower := adoquery1.FieldByName('Power').AsInteger;
if adoquery1.fieldbyname('Def').asstring <> '' then
cards[z].Cdef := adoquery1.FieldByName('Def').AsInteger;
if adoquery1.FieldByName('Type').AsString = 'Spell' then
cards[z].Cspell := true
else
cards[z].Cspell := false;
if adoquery1.FieldByName('Target').AsString = 'yes' then
cards[z].SetTargetTrue
else
cards[z].settargetfalse;
//based on color change background
cards[z].Background.LoadFromFile(format('%s\pics\%s.png',[maindir,cards[z].Ccolor]));
adoquery1.Next;
cards[z].repaint;
z:=z+1;
end;
end;
//cards.Free; if i free this it removes all the cards added to it..
end;
Upvotes: 0
Views: 220
Reputation: 612794
The constructor for TObjectList<T>
receives a parameter named AOwnsObjects
which specifies who is to be responsible for freeing the objects. If you pass True
then the list has that responsibility. Otherwise, the responsibility remains with you.
constructor Create(AOwnsObjects: Boolean = True); overload;
The parameter has a default value of True
and I presume that you are calling the constructor without specifying that parameter. Hence you get the default behaviour – the list owns its members.
The documentation says it like this:
The AOwnsObjects parameter is a boolean that indicates whether object entries are owned by the list. If the object is owned, when the entry is removed from the list, the object is freed. The OwnsObjects property is set from the value of this parameter. The default is true.
Now, if you want this particular list instance not to free its members, then there is little to be gained from using TObjectList<T>
. You may as well use plain old TList<T>
.
Upvotes: 5