问题
(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 singleTGenericHoldingResultSet
, which is set tonil
and lazy-loaded from the database if and when required.- The
TGenericHoldingResultSet
contains a dynamic array ofTGenericHoldingResult
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<TGenericHoldingResult>);
and your resultArray
as TArray<TGenericHoldingResult>
.
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.
来源:https://stackoverflow.com/questions/22140387/why-am-i-receiving-an-error-about-delphi-incompatible-types-array-and-dynamic-a