This question has come up in the newsgroups reasonably frequently even though there is a help topic all about it filed in the index under the entry “record constants,” so be sure to consult the help as well.
Let us begin with an example from the Delphi source code. Consider the
UtilWindowClass variable from the
Classes unit. Delphi uses the variable in implementing the
AllocateHWnd function. Since most of the fields are static
and known in advance, the variable is initialized where it is declared,
as shown in Listing 1. Only the hInstance field
gets set at run time.
Listing 1
A record variable with initialization from Classes.pas
var
UtilWindowClass: TWndClass = (
style: 0;
lpfnWndProc: @DefWindowProc;
cbClsExtra: 0;
cbWndExtra: 0;
hInstance: 0;
hIcon: 0;
hCursor: 0;
hbrBackground: 0;
lpszMenuName: nil;
lpszClassName: 'TPUtilWindow');
Note that the entire value is wrapped in parentheses, and each field name precedes a constant expression. Semicolons separate the pairs of names and values.
The fields must occur in the same order in which they appear in the record type’s declaration. Any field may be omitted, but all subsequent fields must also be omitted. Any omitted field is initialized with the default value for its type.
Arrays of records
To initialize an array constant, the elements’ values need to appear in a comma-separated list within a set of parentheses. Combine this with the syntax above for record constants to reveal that arrays of records should be initialized with comma-separated lists of parenthesized semicolon-separated lists of field: value pairs.
For example, suppose a simple command interpreter has a handful built-in commands, each implemented with a different function. The program could use a record type to associate a command name with a handler function and a short description of the command, and shown below.
Listing 2
Type declarations for a simple command interpreter
type
TArgArray = array of WideString;
TCommandProcessor = procedure(const Arguments: TArgArray);
TCommand = record
Command: WideString;
Processor: TCommandProcessor;
Description: PResStringRec;
end;
The program could then use an array to keep a list of all the built-in
functions the program recognizes. As with all array constants, the array
must have constant dimensions; Delphi does not allow dynamic-array
constants other than nil.
Listing 3
An array of built-in commands for a simple command interpreter
// Declarations of command handlers
procedure DoHelp(const Args: TArgArray); forward;
procedure DoExit(const Args: TArgArray); forward;
procedure DoChdir(const Args: TArgArray); forward;
procedure DoHistory(const Args: TArgArray); forward;
resourcestring
// Help messages
RsHelp = 'Print this help message';
RsExit = 'Quit the command interpreter';
RsChdir = 'Change the working directory';
RsHistory = 'Display the command history';
const
{$TYPEDADDRESS OFF}
Builtins: array[0..4] of TCommand = (
(Command: 'help'; Processor: DoHelp; Description: @RsHelp),
(Command: 'exit'; Processor: DoExit; Description: @RsExit),
(Command: 'cd'; Processor: DoChdir; Description: @RsChdir),
(Command: 'chdir'; Processor: DoChdir; Description: @RsChdir),
(Command: 'history'; Processor: DoHistory; Description: @RsHistory)
);
{$TYPEDADDRESS ON}