I'm migrating a legacy Delphi application to Delphi-XE2, and I'm wondering if there's a good reason to replace the arrays defined as Array of MyType
to TArray<MyType>
. So the question is what are the pros and cons of TArray<T>
usage instead of Array of MyType?
3 Answers
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.

- 601,492
- 42
- 1,072
- 1,490
-
2What about bloated code with generics? Was the problem solved in XE2/XE3? I would never recommend declare a variable as TArray
. – kludg Jan 17 '13 at 16:13 -
I like generic collections because of its convenience methods already built in. Plus, I can change implementations easily and get access to all sort of crazy stuff. – Leonardo Herrera Jan 17 '13 at 16:14
-
1@Serg - I think that's still an issue, but for lists and dictionaries I can live with that extra fat. – Leonardo Herrera Jan 17 '13 at 16:14
-
@Serg, you wouldn't declare a variable as TArray
, rather TArray – Uwe Raabe Jan 17 '13 at 16:17or TArray or so. What code bloat are you refering to? Is it related to TArray or to generics in general? -
7@Serg: That hasn't been fixed, but it doesn't apply here. The problem is that methods get duplicated multiple times, but `TArray
` isn't a class, it's an array. So there are no methods to duplicate, and therefore no code bloat. – Mason Wheeler Jan 17 '13 at 16:18 -
5I very rarely find `TArray
` used but it's probably because Delphi developers still mostly write code like it's 1996. It's a conservative approach to ignore new syntax for at least a decade. (grin) – Warren P Jan 17 '13 at 18:21 -
4@Warren Our codebase uses it exclusively for the reasons outlined in my answer. It's a no-brainer in my view. – David Heffernan Jan 17 '13 at 18:31
-
So to summarize, this is a workaround for a compiler bug on array type resolution. – Eric Grange Jan 18 '13 at 04:44
-
Well, all the behaviour is as designed. Type identity rules go back a long way. – David Heffernan Jan 18 '13 at 07:32
-
But they screwed all those "rules" for the sake of practical usage in all cases but the arrays. The very fact that you can assign strings with implicit typecasting, the very existing of shows how little they care about "ages-blessed rules". So while it is not a "bug" in strict sense, it is still wrong design. @Eric: http://stackoverflow.com/questions/11029353/ – Arioch 'The Jan 18 '13 at 08:09
-
5One important aspect of declaring constant array arguments in methods, use `AMethod(const a : array of T);` instead of `AMethod(const a : TArray
);`. The former accepts passing any array of T, also constant expressions like calling `AMethod([1,2,3]);`, while the latter only accepts parameters of type `TArray – LU RD Jun 18 '13 at 09:12`. -
@LURD I agree 100%. For parameters always use open arrays where possible. They are the most flexible type for an array. – David Heffernan Jun 18 '13 at 11:21
-
@Arioch Yes, because following rules designed in a different era, when designing new features, is much more important than making something useful. That's just silly. Had they done what you said generics would be useless. – David Heffernan Feb 11 '17 at 11:49
-
@DavidHeffernan Keeping rules "designed in a different era" non-revised in new era is obscurantism. They are not divine Holy Scripture, are them ? Now, that would not make generics useless, that would make non-generics more useful. – Arioch 'The Feb 12 '17 at 20:54
-
@arioch Nope, it would make them useless – David Heffernan Feb 12 '17 at 20:55
-
@DavidHeffernan Nope, it would not. – Arioch 'The Feb 14 '17 at 21:30
-
@Arioch'The How would you implement `TList
.ToArray` then? – David Heffernan Feb 14 '17 at 21:31 -
@DavidHeffernan exactly the same. `array of Integer` would be a total synonym of `TArray
` because of `type TArray – Arioch 'The Feb 15 '17 at 10:55= array of integer`. Sure, that is not Wirth's Pascal - but DYNAMIC arrays never were Wirth's Pascal anyway, no? Rules should be UNIFORM, thus simple and polluting not the attention span. For those who wants - explicitly wants - to make it different, there should be working "type X = type Y" declaration that ALWAYS prohibits assignment without EXPLICIT typecast. So `type TFileName = type string; var s1: string; s2: TFileName; s1 := s2` fails always. -
The very notion of "assignment-compatible" types is an ugly hack instead of fixing the language, and should be get rid of. Types either are compatible (identical or implicitly typecasted), or not. Different types either can be explicitly typecasted or not. The `type X = Y;` and `type X = type Y;` statements should cause absolutely identical effects on the variables use for any kind of X and Y, generic or not, simple or structured, etc. Non-uniformity is to be considered a language design bug to be fixed, not ugly-hack-arounded. – Arioch 'The Feb 15 '17 at 10:59
-
@Arioch'The So your idea is that the `a := b` in the second excerpt of my answer above should compile? – David Heffernan Feb 15 '17 at 11:15
-
I some SPECIFIC cases you can use types defined by Borland like TIntegerDynArray in System.Types – Gabriel Sep 15 '19 at 08:48
You can initialize TArray<T>
with values with one construct:
var
LArray: TArray<Integer>;
begin
LArray := TArray<Integer>.Create(1, 2, 3, 4);
For array of Integer
you would need to write much more code:
var
LArray: array of Integer;
begin
SetLength(LArray, 4);
LArray[0] := 1;
LArray[1] := 2;
LArray[2] := 3;
LArray[3] := 4;

- 5,485
- 1
- 25
- 35
-
13`type TMyIntArr = array of integer; var LArray : TMyIntArr; LArray := TMyIntArr.Create(1,2,3,4);` works fine. – LU RD Jan 17 '13 at 16:30
-
5@LURD: +1, and it works in Delphi 2007 as well as in later versions that support generics (and with types other than integer, to make sure that's clear). – Ken White Jan 17 '13 at 17:06
-
Beware of the Create array pseudo-constructor, the compiler handles it *extremely* poorly, so use it only in non critical code. – Eric Grange Jan 18 '13 at 04:47
-
2@EricGrange, can you exemplify? I disassembled the generic array create and the dynamic array create in XE3 and the compiler emits the same code. Looks ok to me. – LU RD Jan 18 '13 at 07:47
-
@Eric Example please. Without an example this is FUD. With an example it's a good comment. – David Heffernan Jan 19 '13 at 23:14
-
1Sorry, for the delay, I don't check answers too often here, check the asm for aig : Tarray
; ain : array of Integer; begin aig:=TArray – Eric Grange Feb 15 '13 at 09:30.Create(1, 2); SetLength(ain, 2); ain[0]:=1; ain[1]:=2; In the first case, you get an array clear, a set length, a wordy assignment for the values, and an array assign, in the second case, you get just a set length and a straight assignment for the values. -
1Posted an article with more details on the subject: http://delphitools.info/2013/02/18/delphi-array-constructors-performance-or-lack-of/ – Eric Grange Feb 18 '13 at 08:26
-
2@Eric: From reading your article, I think the clarification should be put in here that it might be less performant in some speed-critical situations to use the Create array pseudo-contructor. Having read the above comments, I thought you were saying that it was buggy. Good article, though. – jep Jun 24 '13 at 16:48
-
1You can also do `LArray := [1,2,3,4]`, this might have been introduced in a more recent version of Delphi. – Alister Jan 15 '18 at 01:32
It comes in handy for function results.
Example:
The following is not allowed in Delphi. You need to declare a separate type here. What a waste of time.
function MyFunc:array of integer;
begin
end;
Wait, generics to the resque:
function MyFunc:TArray<integer>;
begin
end;

- 23,603
- 7
- 78
- 122
-
8Well, let's be fair, TIntegerDynArray was introduced in what? D4? D6? So you should use an own defined type. – Marco van de Voort Aug 22 '14 at 08:52