delphidelphi-11-alexandria

Why does a dynamic array become an incompatible type if placed inside a record or class?


Why does a dynamic array of string become incompatible with other dynamic array of string when placed inside a record or class?

type
  TRec = record
    ArrayInRecord: array of string;
  end;

var
  Rec: TRec;
  SimpleArray1, SimpleArray2, CombinedArrayOK, CombinedArrayFail: array of string;

begin
  SimpleArray1 := ['1', '2'];
  SimpleArray2 := ['3', '4'];
  CombinedArrayOK := SimpleArray1 + SimpleArray2;  // No problem here

  Rec.ArrayInRecord := ['5', '6'];
  CombinedArrayFail := SimpleArray1 + Rec.ArrayInRecord;  // E2008 Incompatible types
end;

Solution

  • Why does a dynamic array of string become incompatible with other dynamic array of string when placed inside a record or class?

    Actually, this has nothing specifically to do with the presence of classes or records.

    Indeed, even this fails:

    var
      SimpleArray1, SimpleArray2, CombinedArrayOK, CombinedArrayFail: array of string;
      SimpleArray3: array of string;
    
    begin
      SimpleArray1 := ['1', '2'];
      SimpleArray2 := ['3', '4'];
      CombinedArrayOK := SimpleArray1 + SimpleArray2;  // No problem here
    
      SimpleArray3 := ['3', '4'];
      CombinedArrayFail := SimpleArray1 + SimpleArray3;  // E2008 Incompatible types
    end;
    

    The issue is simply that each array of string introduces a new type in the type system.

    Classically, the solution would be to introduce your own array type:

    type
      TDynStringArray = array of string;
    
    var
      SimpleArray1, SimpleArray2, CombinedArrayOK, CombinedArrayFail: TDynStringArray;
      SimpleArray3: TDynStringArray;
    
    begin
      SimpleArray1 := ['1', '2'];
      SimpleArray2 := ['3', '4'];
      CombinedArrayOK := SimpleArray1 + SimpleArray2;  // No problem here
    
      SimpleArray3 := ['3', '4'];
      CombinedArrayFail := SimpleArray1 + SimpleArray3;  // No problem here either!
    end.
    

    Then you would have needed to always use this type.

    But in modern versions of Delphi, you don't need to do that. Instead, just use TArray<string> which is already defined in the RTL:

    var
      SimpleArray1, SimpleArray2, CombinedArrayOK, CombinedArrayFail: TArray<string>;
      SimpleArray3: TArray<string>;
    
    begin
      SimpleArray1 := ['1', '2'];
      SimpleArray2 := ['3', '4'];
      CombinedArrayOK := SimpleArray1 + SimpleArray2;  // No problem here
    
      SimpleArray3 := ['3', '4'];
      CombinedArrayFail := SimpleArray1 + SimpleArray3;  // No problem here either!
    end.
    

    (Introducing a custom type or using TArray<string> is also the solution to the related and common "How to return an array from a function?" question.)