Dynamic Arrays
A SAL dynamic array can grow when an indexed element is accessed, including when an element is passed as a receive argument. SalArray<T> preserves that behavior. A native .NET array has a fixed length, and a List<T> indexer does not create missing elements merely because an index was requested.
Declaration and Growth
String: strArray[*]
The generic PPJ form is:
SalArray<SalString> strArray = new SalArray<SalString>();
strArray[10] = "last";
For a zero-based dynamic array, index 10 requires positions 0 through 10. Those are eleven positions, not ten. Skipping directly to a high index can therefore allocate much more storage than the number of values explicitly assigned.
Index: 0 1 2 ... 9 10
Value: default-initialized ... "last"
└──────── eleven positions ────┘
Do not assume that intermediate default values are the same as business-valid values. For arrays of objects, distinguish an uninitialized element from an object whose fields are empty.
The older SalString.Array spelling appears in .NET 1.1-era examples. It is an alternative to the generic declaration, not a second declaration of the same variable to paste into a method.
Declared Bounds
SAL arrays can specify bounds and multiple dimensions. For example:
String: strArray[2:10]
The corresponding declaration can use PPJ's bounds string:
SalArray<SalString> strArray = new SalArray<SalString>("2:10");
The logical indices run from 2 through 10 inclusive: nine elements. Preserve the declared lower bound rather than rewriting every loop to start at zero. Use the applicable PPJ bounds-query API when the bounds are not known at the call site. A bounded declaration is not a promise that out-of-range accesses will behave like an unbounded dynamic array.
Array Elements by Reference
The SalArray<T> indexer is a property. It is not a C# array element that can be passed directly as ref. The generated bridge obtains the backing array and ensures the requested index exists before passing the element by reference.
Call SalGetItemName(hWndItem, strArray[10])
For a zero-based one-dimensional dynamic array, the generated pattern is:
Sal.GetItemName(Sys.hWndItem, ref strArray.GetArray(10)[10]);
Read this from the inside out:
GetArray(10)ensures access to index 10 in the reviewed runtime and returns the backing array.[10]selects an actual backing-array element.refallows the function to replace that element, so the result is visible throughstrArray[10].
The example is deliberately zero-based. Preserve the generator's target-specific handling for nonzero bounds and multiple dimensions rather than generalizing native-array indexing from this one line.
Bounds and Lifetime
Do not keep a reference to the backing array across operations that may grow or replace it. An old reference can refer to the previous storage rather than the current PPJ array. Prefer ordinary PPJ indexing except at the immediate receive-parameter boundary.
Before replacing a SAL array with a .NET collection, test empty arrays, high sparse indices, nonzero lower bounds, multiple dimensions, and receive arguments that cause growth. Also check enumeration: the count of allocated positions is not necessarily the count of meaningful records. See LINQ Support when filtering an array.