Delphi Clinic C++Builder Gate Training & Consultancy Delphi Notes Weblog Dr.Bob's Webshop
Bob Swart (aka Drs.Bob) Dr.Bob's Delphi Clinics Dr.Bob's Delphi Courseware Manuals
View Bob Swart's profile on LinkedIn Drs.Bob's Delphi Notes
These are the voyages using Delphi Enterprise (and Architect). Its mission: to explore strange, new worlds. To design and build new applications. To boldly go...
Title:

Dynamic arrays that start at index 1...

Author: Bob Swart
Posted: 3/18/2010 1:38:56 PM (GMT+1)
Content:

Dynamic arrays always start at index 0, but sometimes people ask me if you really cannot have a dynamic array that starts at 1. Sure you can, if you write a little wrapper around it...

Here's a simple TDynamicInteger class, using a default array property, with a getter and setter that subtract 1 from the given index (so we can use 1, but it will actually be 0).

type
TDynamicInteger = class
private

FArray: Array of Integer;
function GetValue(Index: Integer): Integer;
procedure SetValue(Index, Value: Integer);
function GetLength: Integer;
procedure SetLength(const Value: Integer);
public
constructor Create(Size: Integer);
destructor Destroy; override;
public
property Length: Integer read GetLength write SetLength;
property Value[index: integer]: Integer read GetValue write SetValue; default;
end;

(* TDynamicInteger *)

constructor TDynamicInteger.Create(Size: Integer);
begin
inherited Create;
System.SetLength(FArray, Size)
end;

destructor TDynamicInteger.Destroy;
begin
FArray := nil;
inherited;
end;

function TDynamicInteger.GetLength: Integer;
begin
Result := System.Length(FArray)
end;

procedure TDynamicInteger.SetLength(const Value: Integer);
begin
System.SetLength(FArray, Value)
end;

function TDynamicInteger.GetValue(Index: Integer): Integer;
begin
Result := FArray[Index-1] // 1-based array
end;

procedure TDynamicInteger.SetValue(Index, Value: Integer);
begin
FArray[Index-1] := Value // 1-based array
end;

Note that we can set the length using the argument of the constructor, or just by assigning a value to the Length property.

Example usage:
 var 
X: TDynamicInteger;
initialization
X := TDynamicInteger.Create(4);
// X.Length := 4;
X[1] := 1;
X[2] := 2;
X[3] := 3;
X[4] := 4;
finalization
X.Free
end.

In my upcoming Delphi 2010 Development Essentials I will use this example and even turn it into a template class so you can have 1-based arrays of any type!

Back  


8 Comments

AuthorPostedComments
Andreas Hausladen 10/03/18 19:07:59To speed things up all the methods should be inline.
Andreas Hausladen 10/03/18 19:11:11And if you change the type from "class" to "record" and remove the destructor and "inherited Create" call. The access to the array becomes almost as fast as the access to a normal dynamic array. And you don't have to worry about when to call Free.
Bob Swart 10/03/18 19:40:34Great feedback Andreas, thanks a lot.
Alan Clark 10/03/18 20:15:32It's beside the point, but in Delphi 2009 + you could have a generic TDynamicType<> class which would allow any type to be stored in it, not just integers.
Bob Swart 10/03/18 21:48:35@Alan: read the last line that I wrote: I will use this example and even turn it into a template class so you can have 1-based arrays of any type!, but thanks for the suggestion ;-)
Craven Weasel 10/03/18 22:44:56A million bugs would have been prevented if Delphi had make lists index from 1 to count, rather than zero to count - 1. It's totally counter intuitive...
Delphi Noob 10/03/19 10:31:14@Craven yes but I guess it has a reason - to be consistent with what Microsoft did in COMs.
Denis A. 10/03/19 12:24:05If you convert it to a record, as Andreas suggested, beware that you will probably run into Delphi bug #44634 http://qc.embarcadero.com/wc/qcmain.aspx?d=44634


New Comment (max. 2048 characters, no HTML):

Name:
Comment:



This webpage © 2005-2019 by Bob Swart (aka Dr.Bob - www.drbob42.com). All Rights Reserved.