为什么我收到有关Delphi不兼容类型(数组和动态数组)的错误?

mag*_*nus 4 arrays delphi dynamic-data

(编辑:以下是针对以Windows为目标的Delphi应用程序中的Are对象引用计数,如果是,它的目的是什么?以及Delphi中的动态数组和内存管理).

我有两个类(TGenericHoldingSummary,TGenericHoldingResultSet)和一个记录(TGenericHoldingResult).

  • TGenericHoldingSummary包含一个TGenericHoldingResultSet,nil如果需要,可以从数据库设置并延迟加载.
  • 该TGenericHoldingResultSet包含的动态数组TGenericHoldingResult记录.

在下面,错误是在TGenericHoldingResultSet构造函数中的赋值.

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;
Run Code Online (Sandbox Code Playgroud)

错误如下:

[DCC Error] GenericHolding.pas(302): E2010 Incompatible types: 'Dynamic array' and 'Array'
Run Code Online (Sandbox Code Playgroud)

LU *_* RD 5

您无法将打开的数组分配给动态数组.见Open Array Parameters.

注意:开放数组参数的语法类似于动态数组类型的语法,但它们并不意味着相同的事情.前面的示例创建了一个函数,该函数接受任何Char元素数组,包括(但不限于)动态数组.要声明必须是动态数组的参数,您需要指定类型标识符:

type TDynamicCharArray = array of Char;
function Find(const A: TDynamicCharArray): Integer;
Run Code Online (Sandbox Code Playgroud)

open arrays可以在此处找到有关动态数组的用例和差异的一个很好的总结:Open array parameters.


如果您有支持泛型的Delphi版本,则可以声明构造函数头:

constructor TGenericHoldingResultSet.Create(parent : TGenericHoldingSummary; 
  const resArr : TArray<TGenericHoldingResult>);
Run Code Online (Sandbox Code Playgroud)

和你resultArray一样TArray<TGenericHoldingResult>.

这将避免必须为数组声明特定类型.

正如David所指出的,开放阵列具有一个优势,因为它们具有更广泛的用例,并且应该尽可能使用.