This post continues the series of The Delphi Language Chapter teasers from Jon Shemitz’ .NET 2.0 for Delphi Programmers book.
Last time we looked at multi-unit namespace support. Now we will jump to a new array syntax supported in .NET.
Note that I do not get any royalties from the book and I highly recommend that you get your own copy – for instance at Amazon.
"New array syntax
While native Delphi supports both static and dynamic arrays, Delphi for .NET now also supports multi-dimensional, rectangular dynamic arrays. These differ from jagged array of arrays in that there is only a single, continuous block of memory allocated for the items in it, and the size of all dimensions can be set dynamically at runtime. This is mostly a performance and memory usage optimization, but it is also required to be able to interface with external code that uses them.
The syntax to declare a multi-dimensional dynamic array is array[,] with one comma for each extra dimension. To allocate a new array, use the New(array [dim1, dim2 ..] of TElement) syntax. To change the size of an existing array, use SetLength with one or more dimension parameters – this will preserve the contents of the array.
var
MyArray: array of integer;
JaggedArray: array of array of integer;
MyMatrix: array[,] of integer;
MyCube: array[,,] of integer;
begin
MyArray := New(array [4] of integer);
JaggedArray := New(array [3] of array of integer);
MyMatrix := New(array [3,3] of integer);
MyCube := New(array [2,2,2] of integer);
SetLength(MyMatrix, 10, 20);
SetLength(MyCube, 10, 20, 30);
end;
Note: While it is possible to create new arrays using SetLength, the New syntax generates slightly smaller and more efficient code. And SetLength cannot currently (Delphi 2006) be used to create a new multi-dimensional [,] array.
There are two new ways to create a new initialized dynamic array from a list of elements. You can use the New statement and follow the array type with a parantesed list of elements. Or you can use a new TArrayType.Create constructor syntax with the elements as parameters – this syntax is also supported in Win32.
begin
MyArray := New(array[] of integer, (1, 2, 3));
JaggedArray := New(array[] of array[] of integer,
(New(array[] of integer, (1, 2, 3)),
New(array[] of integer, (1, 2)),
New(array[] of integer, (1))));
MyMatrix := New(array[,] of integer, ((1,2,3), (4,5,6)));
MyCube := New(array[,,] of integer, (((1,2), (5,6)), ((3,4), (7,8))));
MyArray := TIntegerArray.Create(1, 2, 3);
JaggedArray := TJaggedArray.Create(
TIntegerArray.Create(1, 2, 3),
TIntegerArray.Create(1, 3),
TIntegerArray.Create(1));
end;
This way of initializing dynamic arrays inline is a great improvement of the old way of first allocating the array using SetLength and then explicitly setting the value of each indexed element. This is particularly useful when calling one of the many FCL methods that have array parameters.
unit NewArraySyntaxU;
interface
procedure Test;
implementation
type
TStaticIntegerArray = array[0..5] of integer;
TIntegerArray = array of integer;
TJaggedArray = array of TIntegerArray;
{$IFDEF CLR}
TIntegerMatrix = array[,] of integer;
TIntegerCube= array[,,] of integer;
{$ENDIF}
{$IFDEF CLR}
procedure InnerDumpArray(const Prefix: string; A: System.Array);
var
O: TObject;
begin
write(Prefix);
for O in A do
begin
if O is System.Array
then InnerDumpArray(#13#10' ', System.Array(O))
else Write(O, ', ');
end;
end;
procedure DumpArray(const Name: string; A: System.Array);
begin
write(Name, ' (Rank=', A.Rank, ')' );
InnerDumpArray(': ', A);
Writeln;
end;
{$ELSE}
procedure DumpArray(const Name: string; const A: array of integer); overload;
var
I: Integer;
begin
write(Name, ': ');
for I in A do
Write(I, ', ');
Writeln;
end;
procedure DumpArray(const Name: string; const A: TJaggedArray); overload;
var
I: Integer;
IA : TIntegerArray;
begin
writeln(Name, ': ');
for IA in A do
begin
write(' ');
for I in IA do
Write(I, ', ');
Writeln;
end;
end;
{$ENDIF}
procedure Test;
var
MyStatics: TStaticIntegerArray;
MyArray: TIntegerArray;
JaggedArray: TJaggedArray;
I: integer;
{$IFDEF CLR}
MyMatrix: TIntegerMatrix;
MyCube: TIntegerCube;
{$ENDIF}
begin
MyStatics[1] := 42;
DumpArray('MyStatics', MyStatics);
{$IFDEF CLR}
MyArray := New(array [4] of integer);
MyArray[0] := 13;
DumpArray('MyArray1', MyArray);
JaggedArray := New(array [3] of array of integer);
for I := Low(JaggedArray) to High(JaggedArray) do
JaggedArray[I] := New(array [I+1] of integer);
JaggedArray[0, 0] := 1;
JaggedArray[1, 1] := 2;
JaggedArray[2, 2] := 3;
DumpArray('JaggedArray1', JaggedArray);
JaggedArray := New(TJaggedArray, 3, 2);
JaggedArray[0, 0] := 1;
JaggedArray[1, 1] := 2;
JaggedArray[2, 1] := 3;
DumpArray('JaggedArray2', JaggedArray);
MyArray := New(array[] of integer, (1, 2, 3));
DumpArray('MyArray2', MyArray);
JaggedArray := New(array[] of array[] of integer,
(New(array[] of integer, (1, 2, 3)),
New(array[] of integer, (1, 2)),
New(array[] of integer, (1))));
DumpArray('JaggedArray3', JaggedArray);
{$ENDIF}
SetLength(MyArray, 1);
DumpArray('MyArray3', MyArray);
SetLength(JaggedArray, 3, 3);
JaggedArray[0, 0] := 1;
JaggedArray[1, 1] := 2;
JaggedArray[2, 2] := 3;
DumpArray('JaggedArray4', JaggedArray);
SetLength(JaggedArray, 3);
for I := 0 to 2 do
SetLength(JaggedArray[I], I+1);
JaggedArray[0, 0] := 1;
JaggedArray[1, 1] := 2;
JaggedArray[2, 2] := 3;
DumpArray('JaggedArray5', JaggedArray);
MyArray := TIntegerArray.Create(1, 2, 3);
DumpArray('MyArray4', MyArray);
{$IFDEF CLR}
JaggedArray := TJaggedArray.Create(
TIntegerArray.Create(1, 2, 3),
TIntegerArray.Create(1, 3),
TIntegerArray.Create(1));
DumpArray('JaggedArray6', JaggedArray);
MyMatrix := New(array [3,3] of integer);
MyMatrix[2,2] := 19;
DumpArray('MyMatrix1', MyMatrix);
MyCube := New(array [2,2,2] of integer);
MyCube[1,0,1] := 9;
DumpArray('MyCube1', MyCube);
MyMatrix := New(array[,] of integer, ((1,2,3), (4,5,6)));
DumpArray('MyMatrix2', MyMatrix);
MyCube := New(array[,,] of integer, (((1,2), (5,6)), ((3,4), (7,8))));
DumpArray('MyCube2', MyCube);
SetLength(MyMatrix, 1, 2);
DumpArray('MyMatrix3', MyMatrix);
SetLength(MyCube, 1, 2, 3);
DumpArray('MyCube3', MyCube);
{$ENDIF}
end;
end.
"