A tak w ogóle to dlaczego nie użyjesz generycznych list rekordów? Miałbyś o wiele mniej roboty, bo wypełenie takiej listy czy dopisanie do niej danych wykonuje się czytelnymi metodami. Zastanów się nad tym.
Podasz przykład?
Do przechowywania i wygodnego zarządzania obiektami służy generyczna lista TObjectList. Łatwo do niej dodać obiekt (metoda Add
), usunąć (metoda Remove
lub Extract
), posortować itd. Woła się czytelne metody zamiast bawić w alokowanie pamięci. Ustawienie OwnsObjects
pozwala włączyć lub wyłączyć automatyczne zwalnianie usuwanych z listy obiektów.
Poczytaj, potestuj – zobaczysz różnicę.
przerobiłem moja procedurę AppendArray i teraz tablice maja inne adresy, więc komórki nie są nadpisywane.
[…]
Czy to jest najlepszy sposób?
To nie jest najlepszy sposób, bo to nie jest poprawny sposób. Dlaczego zmieniasz rozmiar tablicy Dest
w pętli? Zrób to raz, przed pętlą, a w niej tylko przepisuj referencje.
Twój problem polega(ł) na tym, że w dwóch listach przechowujesz referencje tych samych obiektów, więc jeśli np. w jednej liście zmodyfikujesz dane obiektu, to w drugiej te dane też będą zmodyfikowane. Jeśli zwolnisz obiekt z jednej listy, to w drugiej adres będzie wskazywać na obszar już zwolniony (czyli na śmieci w pamięci), co może wykrzaczyć program.
Przy czym gdyby Twoja klasa OXERPType
dziedziczyła z TPersistent
, to mógłbyś wygodnie klonować obiekty po prostu wołając metodę Assign
, zamiast ręcznie przepisywać wartości właściwości. Ewentualnie dodaj sobie do tej klasy funkcyjną metodę np. o nazwie Clone
, która zajmie się takim przepisywaniem:
type
OXERPType = class(TRemotable)
{..}
public
function Clone(): OXERPType;
end;
function OXERPType.Clone(): OXERPType;
begin
Result := OXERPType.Create();
Result.FaResult := Self.FaResult;
Result.FaResult_Specified := Self.FaResult_Specified;
Result.FblResult := Self.FblResult;
{..}
end;
Dzięki temu z zewnątrz będzie ją można wywołać w taki sposób:
procedure AppendArray(const ASource: ArrayOfOXERPType; var ADest: ArrayOfOXERPType);
var
SourceLen, DestLen, I: Integer;
begin
SourceLen := Length(ASource);
if SourceLen > 0 then
begin
DestLen := Length(ADest);
SetLength(ADest, DestLen + SourceLen);
for I := Low(ASource) to High(ASource) do
ADest[DestLen + I] := ASource[I].Clone();
end;
end;
Choć gdybym koniecznie musiał używać tablic dynamicznych, to bym sobie do typu macierzy dodał metody i właściwości za pomocą helperów, coby rąk nie brudzić tym Low
, High
, SetLength
itd. Ale nie wiem czy Twoje Delphi na to pozwala.