Appending one element to a dynamic array

Here's a hack with generics which only works with TArray<T>:

type
  TAppender<T> = class
    class procedure Append(var Arr: TArray<T>; Value: T);
  end;

class procedure TAppender<T>.Append;
begin
  SetLength(Arr, Length(Arr)+1);
  Arr[High(Arr)] := Value;
end;

Usage:

var
  TestArray: TArray<Integer>;

begin
  TAppender<Integer>.Append(TestArray, 5);
end.

Every time you call SetLength the memory gets reallocated. Maybe the entire array needs to be copied to a different location. And you who just wanted to add a single element to the array!

Basically: never do this. There are two ways out of it. The simplest case is if you beforehand know the maximum size of the array:

procedure Example1;
var
  data: array of string;
  ActualLength: integer;

  procedure AddElement(const Str: string);
  begin
    data[ActualLength] := Str;
    inc(ActualLength);
  end;

begin

  ActualLength := 0;
  SetLength(data, KNOWN_UPPER_BOUND);

  for ...
    while ...
      repeat ...
        AddElement(SomeString);

  SetLength(data, ActualLength);

end;

Here is a practial example of this approach.

If you don't know any upper bound a priori, then allocate in large chunks:

procedure Example2;
const
  ALLOC_BY = 1024;
var
  data: array of string;
  ActualLength: integer;

  procedure AddElement(const Str: string);
  begin
    if ActualLength = length(data) then
      SetLength(data, length(data) + ALLOC_BY);

    data[ActualLength] := Str;
    inc(ActualLength);
  end;

begin

  ActualLength := 0;
  SetLength(data, ALLOC_BY);

  for ...
    while ...
      repeat ...
        AddElement(SomeString);

  SetLength(data, ActualLength);

end;

This second approach is implemented in the run-time library's TList<T>, TObjectList<T>, TStringList etc. Hence, when you use these classes, it is perfectly fine to append the list one item at a time.


Starting with Delphi XE7 you can do:

SomeDynamicArray := SomeDynamicArray + [NewElement];

ref: Marco Tech Blog, September 18, 2014 : Dynamic Arrays in Delphi XE7

Tags:

Delphi