1

I've noticed something that appears to me as an inconsistency in the generic TArray syntax (and drives me crazy...)

The "constructor" function requires to be called by specifying the type before the function name.

MyArray := TArray<Integer>.Create(3, 2, 1);

The other class functions requires to be called by specifying the type after the function name

TArray.Sort<Integer>(MyArray);

Is there a pratical reason why they did that?

Fabrizio
  • 7,603
  • 6
  • 44
  • 104
  • 3
    Probably because TArray is not a class? TArray on the other side is a class providing some functions to be used with TArray instances. We shouldn't mix TArray and TArray - they are completely different things. – Uwe Raabe Mar 19 '20 at 08:20
  • The first `TArray` is a system type definition of `array of T`. The creation could be written `MyArray := [3,2,1];` The second `TArray` is a class. – LU RD Mar 19 '20 at 08:21
  • Yes, use of `Create` is confusing for a dynamic array. They should have better used `New`- ala C# - or `Init` - ala Turbo Pascal. But it is too late now. – Arnaud Bouchez Mar 19 '20 at 09:40

2 Answers2

3

The generic array is defined like this

TArray<T> = array of T;

This an alias for a dynamic array. Dynamic arrays have an intrinsic Create method. Even non-generic ones.

type
  TMyDynArr = array of Integer;
....
arr := TMyDynArr.Create(0, 1, 2);

This Create method is a compiler intrinsic. Notice how it accepts arbitrary numbers of arguments.

On the other hand there is the class TArray, with its generic Sort method. This is implemented in the RTL. Remember that TArray is never instantiated, it's just a home for generic class methods.

My guess is that adding methods to the dynamic array type requires compiler support because they are intrinsic functions. But adding to TArray is simpler because it is done at the RTL layer, not requiring compiler support.

There's nothing you can do to change anything here, so there is little to be gained by fretting about this. You can't change it. Just get used to it.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
2

The first TArray is a system type definition of array of T. The creation could be written this way as well:

MyArray := [3,2,1]; 

The second TArray is a class defined in Generics.Collections.

They have nothing to do with each other.


Note also that the TArray class way of using generics is called Parameterized Methods.

Type
  TArray = class
    ...
    class procedure Sort<T>(var Values: array of T); overload; static;
    ...
  end; 

That is a way to reduce code duplication.

LU RD
  • 34,438
  • 5
  • 88
  • 296
  • Of course, Embarcadero could have put the type parameter on the class name instead of on the methods (so you would have written `TArray.Sort()` instead). However, then this `TArray` class would have collided with the `TArray = array of T` type. I suppose you could have solved this by instead creating a record helper for `TArray = array of T`, but that is, unfortunately, [not possible](https://stackoverflow.com/a/60632180/282848). – Andreas Rejbrand Mar 19 '20 at 09:32
  • @AndreasRejbrand, yes that is also a probable explanation. If the compiler was designed in a better way, the type could have been inferred, so you could write `TArray.Sort(MyArray);` – LU RD Mar 19 '20 at 09:52