Why am I receiving an error about Delphi incompatible types (array and dynamic array)?

匿名 (未验证) 提交于 2019-12-03 01:58:03

问题:

(EDIT: This is following on from Are objects reference counted in Windows-targeted Delphi applications, and if so, what is its purpose? and Dynamic arrays and memory management in Delphi).

I have two classes (TGenericHoldingSummary, TGenericHoldingResultSet) and one record (TGenericHoldingResult).

  • TGenericHoldingSummary contains a single TGenericHoldingResultSet, which is set to nil and lazy-loaded from the database if and when required.
  • The TGenericHoldingResultSet contains a dynamic array of TGenericHoldingResult records.

In the below, the error is at the assignment in the TGenericHoldingResultSet constructor.

TGenericHoldingResult = record   code : Integer;   level : String;   msg : String; end;  TGenericHoldingResultSet = class(TObject)   public     // Lifecycle     constructor Create(parent : TGenericHoldingSummary; resArr : Array of TGenericHoldingResult);     destructor Destroy;     // Accessors     function ResultCount() : Integer;     function Result(i : Integer) : TGenericHoldingResult;   private     // Variables     summary : TGenericHoldingSummary;     resultArray : Array of TGenericHoldingResult; end;  TGenericHoldingSummary = class(TObject) public   // Note that the summary object 'owns' the results, and deallocates   // its memory in the destructor.   function getResultSet: TGenericHoldingResultSet; private   // Member variables   resultSet: TGenericHoldingResultSet; end;  // Note that the summary object 'owns' the results, and deallocates // its memory in the destructor. function TGenericHoldingSummary.getResultSet() : TGenericHoldingResultSet; var   sql : String;   i : Integer;   resultArray : Array of TGenericHoldingResult; begin   if resultSet = nil then   begin     // Get results via SQL.     SetLength(resultArray, holding.clientDataSet.RecordCount);      for i := 0 to holding.clientDataSet.RecordCount - 1 do     begin       resultArray[i].code := holding.clientDataSet.FieldByName('code').AsInteger;       resultArray[i].level := holding.clientDataSet.FieldByName('level').AsString;       resultArray[i].msg := holding.clientDataSet.FieldByName('message').AsString;     end;      resultSet := TGenericHoldingResultSet.Create(self, resultArray);   end;    result := resultSet; end;  // Lifecycle constructor TGenericHoldingResultSet.Create(parent : TGenericHoldingSummary; resArr : Array of TGenericHoldingResult); begin   summary := parent;   // The following *should* work, shouldn't it?   // E.g., seeing as dynamic arrays a reference counted in Delphi for   // all platforms, this should simply increment the reference count.   resultArray := resArr; end; 

The error is below:

[DCC Error] GenericHolding.pas(302): E2010 Incompatible types: 'Dynamic array' and 'Array' 

回答1:

You cannot assign an open array to a dynamic array. See Open Array Parameters.

Note: The syntax of open array parameters resembles that of dynamic array types, but they do not mean the same thing. The previous example creates a function that takes any array of Char elements, including (but not limited to) dynamic arrays. To declare parameters that must be dynamic arrays, you need to specify a type identifier:

type TDynamicCharArray = array of Char; function Find(const A: TDynamicCharArray): Integer; 

A good summary of the use case of open arrays and the difference with a dynamic array can be found here: Open array parameters.


If you have a Delphi version that supports generics, it is possible to declare the constructor header:

constructor TGenericHoldingResultSet.Create(parent : TGenericHoldingSummary;    const resArr : TArray); 

and your resultArray as TArray.

This will avoid having to declare a specific type for the array.

As noted by David, open arrays have a benefit since they have a broader use case, and should be used when possible.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!