Q:

Appending one element to a dynamic array

This is a very frequent pattern throughout my code:
SetLength(SomeDynamicArray, Length(SomeDynamicArray)+1);
SomeDynamicArray[High(SomeDynamicArray)] := NewElement;

Is there no way to do this in one line?
Edit: This is incredibly inefficient. I know. I use dynamic arrays (in my own code, in my personal projects which only I use) foremost because they are the easiest to use, and I just need to get things done with as little code as possible.

A:

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.

A:

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.

A:

Starting with Delphi XE7 you can do:
SomeDynamicArray := SomeDynamicArray + [NewElement];

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

