The main advantage is less onerous type identity rules. Consider:
a: array of Integer;
b: array of Integer;
These two variables are not assignment compatible. It is a compiler error to write:
a := b;
On the other hand if you use the generic syntax:
a: TArray<Integer>;
b: TArray<Integer>;
then these two variables are assignment compatible.
Sure, you can write
type
TIntegerArray = array of Integer;
But all parties need to agree on the same type. It’s fine if all code is in your control, but when using code from a variety of sources, the advent of generic dynamic arrays makes a huge difference.
The other advantage that springs to mind, in similar vein, is that you can readily use the generic array type as the return type of a generic method.
Without the generic array you are compelled to declare a type of this form:
TArrayOfT = array of T
in your generic class, which is rather messy. And if you are writing a generic method in a non-generic class, then you’ve no way to make that declaration. Again the generic array solves the problem.
TMyClass = class
class function Foo<T>: TArray<T>; static;
end;
This all follows on from type compatibility rules described in the documentation like this:
Type Compatibility
Two non-instantiated generics are considered assignment
compatible only if they are identical or are aliases to a
common type.Two instantiated generics are considered assignment
compatible if the base types are identical (or are aliases to a
common type) and the type arguments are identical.