Delphi,传递一个out参数数组

时间:2018-07-05 17:57:59

标签: function delphi pointers

我有很多函数可以查询一个表,检查它是否在一个巨大的数组上有记录,并根据需要进行更新或插入。

它看起来像这样:

function UpdateTableA;
var
    AFieldA,
    AFieldB,
    (...),
    AFieldZ: TField;
begin
    FSqlQuery.SQL.Text :=
        'select fielda, fieldb, (...), fieldz '+
        'from tablea '+
        'where id in (0, 1, 5, 7, 8, (...))'
    ;
    FClientDataset.Open; // this client is connected to FSqlQuery

    AFieldA := FClientDataset.FieldByName('fielda');
    AFieldB := FClientDataset.FieldByName('fieldb');
    (...)
    AFieldZ := FClientDataset.FieldByName('fieldz');

    for Obj in GLongArray do
    begin
        if FClientDataset.locate('id', Obj.id, []) then
            FClientDataset.Edit
        else
            FClientDataset.Insert;

        AFieldA.AsInteger := Obj.ValueA;
        AFieldB.AsInteger := Obj.ValueB;
        (...)
    end;
end;

我可以创建一个函数,在其中将所有TField变量传递到数组中并在那里进行初始化吗?

类似这样的东西:(伪代码)

function SetTFields(AFields: array of out TField);
begin
    for I := 0 to FClientDataset.Fields.Count-1 do
        AFields[I] := FClientDataset.Fields[I];
end;

并在打开FClientDataset之后,像这样使用它:

SetTFields([AFieldA, AFieldB, AFieldC, AFieldD, etc])
or this:
SetTFields([@AFieldA, @AFieldB, @AFieldC, @AFieldD, etc])

如果没有,是否有类似的方法可以完成,而无需复制很多变量?

1 个答案:

答案 0 :(得分:4)

您可以使用以下内容:

type
  PField: ^TField;

function SetTFields(AFields: array of PField);
begin
  for I := 0 to FClientDataset.Fields.Count-1 do
    AFields[I]^ := FClientDataset.Fields[I];
end;

function UpdateTableA;
var
  AFieldA,
  AFieldB,
  (...),
  AFieldZ: TField;
begin
  FSqlQuery.SQL.Text := 'select fielda, fieldb, (...), fieldz '+
    'from tablea '+
    'where id in (0, 1, 5, 7, 8, (...))';
  FClientDataset.Open; // this client is connected to FSqlQuery

  SetTFields([@AFieldA, @AFieldB, (...), @AFieldZ]);

  for Obj in GLongArray do
  begin
    if FClientDataset.Locate('id', Obj.id, []) then
      FClientDataset.Edit
    else
      FClientDataset.Insert;

    AFieldA.AsInteger := Obj.ValueA;
    AFieldB.AsInteger := Obj.ValueB;
    (...)
  end;
end;

或者,您可以使用动态数组代替单个变量,例如:

type
  TFieldArray: array of TField;

function SetTFields(out AFields: TFieldArray);
begin
  SetLength(AFields, FClientDataset.Fields.Count);
  for I := 0 to FClientDataset.Fields.Count-1 do
    AFields[I] := FClientDataset.Fields[I];
end;

function UpdateTableA;
var
  AFields: TFieldArray;
begin
  FSqlQuery.SQL.Text := 'select fielda, fieldb, (...), fieldz '+
    'from tablea '+
    'where id in (0, 1, 5, 7, 8, (...))';
  FClientDataset.Open; // this client is connected to FSqlQuery

  SetTFields(AFields);

  for Obj in GLongArray do
  begin
    if FClientDataset.Locate('id', Obj.id, []) then
      FClientDataset.Edit
    else
      FClientDataset.Insert;

    AFields[0].AsInteger := Obj.ValueA;
    AFields[1].AsInteger := Obj.ValueB;
    (...)
  end;
end;