Skip to content

Latest commit

 

History

History
118 lines (88 loc) · 3.53 KB

File metadata and controls

118 lines (88 loc) · 3.53 KB

PopAndFree<T: class> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

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

Description

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

The length of the array is reduced by one.

Parameters:

  • A - Array from which the element is to be removed and freed. The array is updated in place when the element is deleted.

    Array elements must be TObject descendants.

Preconditions:

  • A must not be empty. An EAssertionFailed exception is raised otherwise.

Note

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

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

Example

This example illustrates how PopAndFree<class T> varies from Pop<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 PopAndFree_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 Push<T>
  SetLength(A, 0);
  TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('C'));
  TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('B'));
  TArrayUtils.Push<TObjectEx>(A, TObjectEx.Create('A'));
  Assert(Length(A) = 3, 'Array length <> 3');
  Assert(TObjectEx.InstanceCount = 3, 'TObjectEx <> 3 instances');
  Assert(TArrayUtils.Last<TObjectEx>(A).ID = 'A', 'Last object ID <> A');

  // Pop last object with PopAndFree<T:class>:
  // this will remove it from the array and free it
  TArrayUtils.PopAndFree<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.Last<TObjectEx>(A).ID = 'B', 'Last object ID <> B');

  // Pop new last object with Pop<T>:
  // this will remove it from the array but not free it
  ShiftedObj := TArrayUtils.Pop<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.Last<TObjectEx>(A).ID = 'C', 'Last 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