4

Does anyone know if it is possible to initialize a record constant array?

procedure TForm1.Button1Click( Sender: TObject );
type
  TMyRec = record
    A: Integer;
  end;
const
  MyArray: TArray< TMyRec > = [ ?, ?, ? ];
begin

end;

thanks!

5
  • 1
    TArray<TMyRec> is a dynamic array of TMyRec. You want MyArr: array[0..2] of TMyRec = ((... Commented Jan 23, 2021 at 21:36
  • Thanks, but the code below compiles, I remember that at some point I had used a syntax that allowed this. const MyArray: TArray <string> = ['a', 'b', 'c']; Commented Jan 23, 2021 at 21:39
  • If so, that was an inline const declaration. But the constant in that case isn't a static array, but a dynamic array. Commented Jan 23, 2021 at 21:39
  • There isn't a static array in the question Commented Jan 23, 2021 at 21:42
  • thanks David, i edit my title! Commented Jan 23, 2021 at 21:44

1 Answer 1

16

Every time you have a question about Delphi, the official documentation should be the first place you visit.

In this case, combining the knowledge from sections Array Constants and Record Constants, we realise that the following syntax is valid:

type
  TMyRec = record
    A, B: Integer;
  end;

const
  MyArray: array[0..2] of TMyRec =
    (
      (A: 1; B: 5),
      (A: 2; B: 10),
      (A: 3; B: 15)
    );

Initially, the question talked about static arrays, but its suggestion TArray<TMyRec> is in fact a dynamic array. By definition, TArray<T> = array of T.

Since Delphi XE7, you can create dynamic array typed constants, as long as the elements are of simple enough types:

const
  A: TArray<Integer> = [11, 22, 33];
  S: TArray<string> = ['alpha', 'beta', 'gamma'];

Since Delphi 10.3, you can even make inline constant declarations, in which case the RHS can even depend on runtime functions. But these are quite far from "true" constants. Think of them as read-only (or assign-once) variables:

begin
  const MyArray: TArray<TPoint> = [Point(1, 5), Point(2, 10), Point(3, 15)];

Hence, if you make a function that creates your record (perhaps a record constructor), you can use an inline constant declaration to create such a constant dynamic array of your record:

type
  TMyRec = record
    A, B: Integer;
  end;

function MyRec(A, B: Integer): TMyRec;
begin
  Result.A := A;
  Result.B := B;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  const MyArray: TArray<TMyRec> = [MyRec(1, 5), MyRec(2, 10), MyRec(3, 15)];
end;

If you are willing to give up some type compatibility, you can also use type inference:

procedure TForm1.FormCreate(Sender: TObject);
begin
  const MyArray = [MyRec(1, 5), MyRec(2, 10), MyRec(3, 15)];
end;
Sign up to request clarification or add additional context in comments.

5 Comments

The most interesting thing is when I have dynamic fields it compiles type TMyRec = record A: Char; B: TArray< Integer >; C: TArray< string >; end; const MyArray: array [ 0 .. 1 ] of TMyRec = ( ( A: 'A'; B: [ 1, 2, 3 ]; C: [ 'abc', 'def', 'ghi' ] ), ( A: 'B'; B: [ 4, 5, 6 ]; C: [ 'jkl', 'mno', 'pqr' ] ) );
@DelphiUser: You are right. You can declare non-inline dynamic array constants. I'll update my answer.
A variant without an additional function is a class function directly next to the TMyRec record definition: class function MyRec(A, B: Integer): TMyRec; static;
@Pavel: Correct. But then it is arguably even better to use a constructor: constructor Create(A, B: Integer);
@AndreasRejbrand Yes. I would forget about that. I have several variants with different overloads, so I have functions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.