Forum > Beginners

[Solved] A (may be stupid ) question about Tcollecion copy

(1/2) > >>

BlueIcaro:
Hi I have a TCollection, and I want copy to other.
If I do

--- Code: ---L2 := L1;
L1.Free;

--- End code ---
When I read L2, is empty.
If I do:

--- Code: --- L2.Assign(L1);
L1.Free;

--- End code ---
I got a runtime Error: EConvertError.

How can I do to avoid copy every item from L1 to L2 using a Loop:

--- Code: ---For I:=0 to L1.count-1 do
begin
I:=L2.Add
I.Bla:=L1.Item[I].Bla;
end;

--- End code ---

Of Couse L1 and L2 are the same type.

A stupid code to test

--- Code: ---program Project1;

{$mode objfpc}{$H+}

uses
 {$IFDEF UNIX}
  cthreads,
      {$ENDIF}
  Classes { you can add units after this };

type

  { MyItem }

  TMyItem = class(TCollectionItem)
  private
    FBla: string;
  published
    property Bla: string read FBla write FBla;
  end;

type

  { TMyList }

  TMyList = class(TCollection)
  private
    function GetItem(Index: integer): TMyItem;
  public
    function Add: TMyItem;
    property Item[Index: integer]: TMyItem read GetItem;
  end;
var
  L1, L2: TMyList;
  E1: TMyItem;
  I: Integer;

  { TMyList }
  function TMyList.GetItem(Index: integer): TMyItem;
  begin
    Result := inherited Items[Index] as TMyItem;
  end;

  function TMyList.Add: TMyItem;
  begin
    Result := inherited Add as TMyItem;
  end;

begin
  Writeln('Test');
  L1 := TMyList.Create(TMyItem);
  L2 := TMyList.Create(TMyItem);
  For I := 0 To 3 do
  begin
    E1:=L1.Add;
    E1.Bla:='asdada';
  end;
  L2.Assign(L1);
  L1.Free;
  For I := 0 To L2.Count-1 do
  begin
    Writeln(L2.Item[I].Bla);
  end;
  L2.Free;
  Readln();
end.

--- End code ---

Thanks in advance

/BlueIcaro



MarkMLl:
You're making a copy of (the address of) the object, rather than creating a new object. The distinction is sometimes referred to as "shallow" vs "deep" copy.

TCollection is fairly low-level, so doesn't have anything like TStringList's Assign() which assigns the content of one instance to another. Unless somebody comes up with a better idea I suspect you'll have to create a new collection and then iterate to transfer each contained object... considering whether these actually need to be deep copied.

I was caught by a variant of this earlier in the week: https://forum.lazarus.freepascal.org/index.php/topic,58870.msg438961.html#msg438961

MarkMLl

marcov:
Override TMyitem.assign.



--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---  { MyItem }   TMyItem = class(TCollectionItem)  private    FBla: string;    procedure assign(T:TPersistent);override; // <-- add this  published    property Bla: string read FBla write FBla;  end; // and its implementationprocedure tmyitem.assign(t:TPersistent);begin   if t is TMyItem then     fbla:=TMyItem(t).bla   else   inherited;end;

Remy Lebeau:

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---L2 := L1;
This merely copies the pointer, not the data.  So, if L2 was previously pointing at an existing TCollection object, you leak that object.  And you leave L2 dangling if you call L1.Free() afterwards.


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---L2.Assign(L1);
This is the correct way to copy the collection data.

The EConvertError exception is simply because you did not implement the Assign() method in your TMyItem class, eg:


--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} ---program Project1; {$mode objfpc}{$H+} uses {$IFDEF UNIX}  cthreads,  {$ENDIF}  Classes { you can add units after this }; type   { MyItem }   TMyItem = class(TCollectionItem)  private    FBla: string;  public    procedure Assign(Source: TPersistent); override;  published    property Bla: string read FBla write FBla;  end; type   { TMyList }   TMyList = class(TCollection)  private    function GetItem(Index: integer): TMyItem;  public    function Add: TMyItem;    property Item[Index: integer]: TMyItem read GetItem;  end; { TMyItem } procedure TMyItem.Assign(Source: TPersistent);begin  if Source is TMyItem then    FBla := TMyItem(Source).Bla  else    inherited;end; { TMyList } function TMyList.GetItem(Index: integer): TMyItem;begin  Result := inherited Items[Index] as TMyItem;end; function TMyList.Add: TMyItem;begin  Result := inherited Add as TMyItem;end; var  L1, L2: TMyList;  E1: TMyItem;  I: Integer;begin  Writeln('Test');  L1 := TMyList.Create(TMyItem);  L2 := TMyList.Create(TMyItem);  For I := 0 To 3 do  begin    E1 := L1.Add;    E1.Bla := 'asdada';  end;  L2.Assign(L1);  L1.Free;  For I := 0 To L2.Count-1 do  begin    Writeln(L2.Item[I].Bla);  end;  L2.Free;  Readln();end.

PascalDragon:

--- Quote from: MarkMLl on April 01, 2022, 06:15:41 pm ---TCollection is fairly low-level, so doesn't have anything like TStringList's Assign() which assigns the content of one instance to another. Unless somebody comes up with a better idea I suspect you'll have to create a new collection and then iterate to transfer each contained object... considering whether these actually need to be deep copied.

--- End quote ---

Ehm...

Navigation

[0] Message Index

[#] Next page

Go to full version