An array is a constant sized list of elements. An array type is expressed with the ``array of` keyword followed by the name of any valid Type; an optional size can be provided in square brackets. The lower bound of an array does not have to be 0.
var x: array of Integer; // an array of undetermined (as of yet) size var y: array [0..9] of Integer; // an array fixed to 10 elements var z: array [5..10] of Integer; // an array fixed to 6 elements, with a lower bound of 5.
Arrays can be made multidimensional, by providing more than one set of bounds.
var x: array[0..9, 0..9] of Integer; // 10x10 = 100 integers var y: array[0.., 0..] of Integer; // an undetermined (but rectangular) number of integers var z: array of array of Integer; // an undetermined (loose) number of integers
It is worth noting that arrays with fixed specified bounds are automatically allocated by the compiler, on the stack as value types, and can be immediately used. These are referred to as Static Arrays.
var x: array[0..9] of Integer; // these 10 integers now exist as space on the stack x := 42; // so we can just set the one at index 3 to "42"
The same holds true for multi-dimensional arrays with fixed bounds. These are allocated as a monolithic block of memory, so essentially
array [0..99] of Integer and
array [0..9, 0..9] of Integer have the same memory representation. Merely the semantics of how the 100 individual items get accessed differs.
var y: array[0..9, 0..9] of Integer; // these 100 integers too exist as space on the stack x[3,8] := 42; // so we can just set the one at index 3 to "42"
Arrays without bounds (or with open bounds) are un-initialized reference types, and set to
nil by default (because, after all, their actual size is not known from the declaration). These are referred to as Dynamic Arrays.
To use, fill these arrays with values, a copy needs to be instantiated using the
var x: array of Integers; // unknown number of Integers, for now x := new Integer; // so we need to allocate 20 of them in memory (indexed 0..19) x := 42; // *now* we can set the one at index 3 to "42"
var x: array [0.., 0..] of Integers; // unknown number of Integers, for now x := new Integer[20,20]; // so we need to allocate 400 of them in memory (indexed 0..19/0..19) x[3,8] := 42; // *now* we can set the one at index 3 to "42"
For loose multi-dimensional dynamic arrays, each level would need to be instantiated manually (since each level can, in theory, contain a different-sized sub-array):
var x: array [0.., 0..] of Integers; // unknown number of Integers, for now x := new array of Integer; // we allocate 50 arrays for dimension one (indexed 0..49) for i: Integer := 0 to 49 do x[i] = new Integer; // and for each, we allocate 20 integers — for a total of 50*20 = 1000 x[3,8] := 15; // now we can set values
Dynamic arrays are always reference types.
Inline arrays are concept specific to arrays on the .NET platform. The inline Type Modifier ensures that memory for the arrays is allocated with the stack space or the memory space of the containing Class or Record.
type MyRecord = public record public Chars: inline array[0..255] of Byte; end;
The above record's size would be 256 bytes, unlike a record with a regular array, which would be stored outside of the record. Inline arrays are specially useful when working with P/Invoke to call native code.
The Inline Array syntax is available on the .NET platform only.
Inline arrays are considered "unsafe". In order to use them, the "Allow Unsafe Code" Compiler Option must be enabled, and any Methods that deal with them must be marked with the
unsafe Member Modifier.