Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is TArray<recordType> different from array of recordType?

I have a record type defined like:

type 
    TRecordType = record
        Field1: string;
        Field2: Variant;
    end;

And a function declaration using it:

function Function1(const Records: TArray<TRecordType>): TAnyOtherClass;

So far so good, but if the function is called like:

Function1([BuildRecord('string', value), BuildRecord('OtherString', otherValue)])

The compiler returns an error:

[DCC Error] AnyUnit.pas(142): E2001 Ordinal type required

I have read some place a long time ago that Delphi's compiler handles generics in a kind of preprocessor with string replacements done before really compiling the code, so I was expecting Function1 to become something like:

function Function1(const Records: array of TRecordType): TAnyOtherClass;

Because TArray is defined TArray<T> = array of T;.

I think it is not happening, because when I changed the function declaration to:

function Function1(const Records: array of TRecordType): TAnyOtherClass;

The code is compiled without errors or warnings.

There is an answer on [this question] 1 that links to an article explaining the difference, but the link there is broken.

So my question is, what means TArray<T> if not array of T?

like image 715
Jean Jung Avatar asked Sep 03 '15 13:09

Jean Jung


1 Answers

Function1([BuildRecord('string', value), BuildRecord('OtherString', otherValue)])

The [...] syntax in your argument is what is known as an open array constructor. This documentation states, with my emphasis:

Open array constructors allow you to construct arrays directly within function and procedure calls. They can be passed only as open array parameters or variant open array parameters.

Your function accepts a (generic) dynamic array type, which is different from an open array. Your function is declared as

function Function1(const Records: TArray<TRecordType>): TAnyOtherClass;

The parameter is a (generic) dynamic array type. An open array parameter would look like this:

function Function1(const Records: array of TRecordType): TAnyOtherClass;

I know this looks very like the declaration of a dynamic array, but it is not. In Delphi, array of has two distinct meanings:

  • In the context of a parameter list, array of is used to declare an open array parameter.
  • Elsewhere, array of defines a dynamic array type.

This overloading of the language syntax is a common cause for confusion.

So, because of all this, the compiler rejects your code, because you are attempting to use an open array constructor with a parameter that is not an open array.

My answer here goes into this issue in more detail: https://stackoverflow.com/a/14383278/505088

I have read some place a long time ago that Delphi's compiler handles generics in a kind of preprocessor and some kind of string replace in code.

I think you are mis-remembering. What you are describing is more akin to C++ templates. Delphi generics are not handled by a preprocessor, not least because Delphi does not have a preprocessor.

like image 85
David Heffernan Avatar answered Oct 06 '22 01:10

David Heffernan