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.
Project: Array Utilities Unit
Unit: DelphiDabbler.Lib.ArrayUtils
Record: TArrayUtils
Applies to: ~>0.1
class procedure ShiftAndFree<T: class>(var A: TArray<T>);
static;
Removes and frees the first 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:
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>.
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.
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;