Welcome to the new DelphiDabbler Code Library Documentation.

This is a new site that's currently running on alpha code. There are going to be bugs. If you discover any, please report them on the site's issues page (GitHub account required). Thanks.

Warning: Many URLs are going to change. Refer to the README file to discover which library project's documentation has been completed.

ShiftAndFree<T: class> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

class procedure ShiftAndFree<T: class>(var A: TArray<T>);
  static;

Description

Removes and frees the first element from a non-empty array of TObject descendants.

The length of the array is reduced by one.

Parameters:

Preconditions:

Note

  1. If it is not necessary to free an object that is shifted off an array then Shift<T> should be used instead of ShiftAndFree<T: class>.

  2. There is no corresponding object version of UnShift<T> for use with ShiftAndFree<T: class>. This is not necessary since un-shifting an object requires no special handling. Just use UnShift<T> where T is set to the required class type.

Example

This example illustrates how ShiftAndFree<class T> varies from Shift<T>.

The example uses custom class TObjectEx that records the number of objects currently instantiated.

type
  TObjectEx = class
  public
    var ID: Char;
    class var InstanceCount: Integer;
    constructor Create(AID: Char);
    destructor Destroy; override;
  end;

{ TObjectEx }

constructor TObjectEx.Create(AID: Char);
begin
  inherited Create;
  ID := AID;
  Inc(InstanceCount);
end;

destructor TObjectEx.Destroy;
begin
  Dec(InstanceCount);
  inherited;
end;

procedure ShiftAndFree_Eg;
var
  A: TArray<TObjectEx>;
  Obj, ShiftedObj: TObjectEx;
begin
  // Start with no objects
  Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');

  // Create array of 3 objects using UnShift<T>
  SetLength(A, 0);
  TArrayUtils.UnShift<TObjectEx>(A, TObjectEx.Create('C'));
  TArrayUtils.UnShift<TObjectEx>(A, TObjectEx.Create('B'));
  TArrayUtils.UnShift<TObjectEx>(A, TObjectEx.Create('A'));
  Assert(Length(A) = 3, 'Array length <> 3');
  Assert(TObjectEx.InstanceCount = 3, 'TObjectEx <> 3 instances');
  Assert(TArrayUtils.First<TObjectEx>(A).ID = 'A', 'First object ID <> A');

  // Pop first object with ShiftAndFree<T:class>:
  // this will remove it from the array and free it
  TArrayUtils.ShiftAndFree<TObjectEx>(A);
  // check object was removed from array
  Assert(Length(A) = 2, 'Array length <> 2');
  // check removed object was freed
  Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
  Assert(TArrayUtils.First<TObjectEx>(A).ID = 'B', 'First object ID <> B');

  // Pop new first object with Shift<T>:
  // this will remove it from the array but not free it
  ShiftedObj := TArrayUtils.Shift<TObjectEx>(A);
  // check object removed from array
  Assert(Length(A) = 1, 'Array length <> 1');
  // check removed object was not freed
  Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
  Assert(TArrayUtils.First<TObjectEx>(A).ID = 'C', 'First object ID <> C');

  // Tidy up remaining un-freed objects
  ShiftedObj.Free;
  for Obj in A do
    Obj.Free;
  Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');
end;

See Also