Skip to content

Latest commit

 

History

History
157 lines (122 loc) · 4.38 KB

File metadata and controls

157 lines (122 loc) · 4.38 KB

DeleteAndFree<T: class> class method

Project: Array Utilities Unit

Unit: DelphiDabbler.Lib.ArrayUtils

Record: TArrayUtils

Applies to: ~>0.1

class procedure DeleteAndFree<T: class>(var A: TArray<T>;
  const AIndex: Integer);
  overload; static;

class procedure DeleteAndFree<T: class>(var A: TArray<T>;
  const AIndices: array of Integer);
  overload; static;

Description

Deletes and frees the element or elements at one or more indices in an array of TObject descendant objects.

Parameters:

  • A - Array from which the elements are to be deleted. The array is updated in place.

    Array elements must be TObject descendants.

  • AIndex - Index of a single element to be deleted. (First overload only.)

    If A is empty, if AIndex < 0 or if AIndexLength(A) then no deletion takes place and A is unchanged.

  • AIndices - An integer array of indices of elements to be deleted and freed. (Second overload only.)

    If any index < 0 or ≥ Length(A) then that index is ignored.

    Duplicate indices are ignored.

    If A is empty then no deletion takes place and A is unchanged.

Example

Both examples below use a custom TObjectEx class that records the number of objects currently instantiated. This is defined as follows:

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;

Example #1

This example illustrates how a single object deleted from an array is freed in addition to being removed from the array.

procedure DeleteAndFree_Eg1;
var
  A: TArray<TObjectEx>;
  Obj: TObjectEx;
begin
  // Start with no objects
  Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');
  // Create array of 3 objects
  A := TArray<TObjectEx>.Create(
    TObjectEx.Create('A'), TObjectEx.Create('B'), TObjectEx.Create('C')
  );
  Assert(Length(A) = 3, 'Array length <> 3');
  Assert(TObjectEx.InstanceCount = 3, 'TObjectEx <> 3 instances');
  Assert(A[1].ID = 'B', 'A[1] <> B');

  // Delete object @ index 1: this will remove it from the array and free it
  TArrayUtils.DeleteAndFree<TObjectEx>(A, 1);
  Assert(Length(A) = 2, 'Array length <> 2');
  Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
  Assert(A[1].ID <> 'B', 'Last object ID = B');
  // Tidy up remaining 2 objects
  for Obj in A do
    Obj.Free;
  Assert(TObjectEx.InstanceCount = 0, 'TObjectEx <> 0 instances');
end;

Example #2

This example shows how multiple objects deleted from an array are freed in addition to being removed from the array.

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

  // Create array of 4 objects
  A := TArray<TObjectEx>.Create(
    TObjectEx.Create('A'), TObjectEx.Create('B'),
    TObjectEx.Create('C'), TObjectEx.Create('D')
  );
  Assert(Length(A) = 4, 'Array length <> 4');
  Assert(TObjectEx.InstanceCount = 4, 'TObjectEx <> 4 instances');
  Assert(A[1].ID = 'B', 'A[1] <> B');
  Assert(A[2].ID = 'C', 'A[2] <> C');

  // Delete objects @ index 1 & 2 with IDs 'B' and 'C':
  // this will remove the objects from the array and free them
  TArrayUtils.DeleteAndFree<TObjectEx>(A, [1, 2]);
  Assert(Length(A) = 2, 'Array length <> 2');
  Assert(TObjectEx.InstanceCount = 2, 'TObjectEx <> 2 instances');
  Constraint := function (const AElem: TObjectEx): Boolean
    begin
      Result := (AElem.ID = 'B') or (AElem.ID = 'C');
    end;
  Assert(
    not TArrayUtils.Some<TObjectEx>(A, Constraint),
    'B or C found in array'
  );

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

See Also