Delphi 在对象中重新检索已分类的TObjectList

Delphi 在对象中重新检索已分类的TObjectList,delphi,delphi-xe2,Delphi,Delphi Xe2,我创建了一个名为TRecord的类来存储数据。我创建了另一个类,它将TRecord类作为objectlist包含在内。我使用TRecord在对象列表中添加记录,然后在完成后将其设置到父类TTableStore.FManyrecords中 我可以检索列表,计数显示相同数量的记录,但它不允许我检索每个记录 问题是我无法访问记录过程/方法,甚至无法定义记录的检索。请参见伪代码的最后一行: TRecord = class(TObject) private FDescription : Var

我创建了一个名为TRecord的类来存储数据。我创建了另一个类,它将TRecord类作为objectlist包含在内。我使用TRecord在对象列表中添加记录,然后在完成后将其设置到父类TTableStore.FManyrecords中

我可以检索列表,计数显示相同数量的记录,但它不允许我检索每个记录

问题是我无法访问记录过程/方法,甚至无法定义记录的检索。请参见伪代码的最后一行:

TRecord = class(TObject)
  private
    FDescription : Variant;
    FDirectDeposit : Double;
  public
    function  GetDescription : Variant;
    function  GetDirectDeposit : Double;
    procedure SetDescription(Value: Variant; DoValidation: Boolean = True);
    procedure SetDirect(Value: Double; DoValidation: Boolean = True);
end;

TTableStore = class(TObject)
  private
    FManyRecords : TObjectList ;
    FTitle2 : Variant;
    FNormalEarn : Double;
  public
    function  GetTitle2 : String;
    function  GetNormalEarn : Double;
    function GetManyRecords: TObjectList;
    procedure SetManyRecords(Value: TObjectList; DoValidation: Boolean = True);
    procedure SetTitle2(Value: String; DoValidation: Boolean = True);
    procedure SetNormalEarn(Value: Double; DoValidation: Boolean = True);
end;

private
  FReportObj : TTableStore;
  FRecord: TRecord;
  objectListTemp: TObjectList;

implementation
  objectListTemp := TObjectList.Create(false);
  FRecord := TRecord.create;

  Frecord.SetDescription…
  Frecord.SetDirect…

  objectListTemp.add(FRecord);

//next...
//(get next record… until eof.)

finally
  FReportObj.SetManyRecords(objectListTemp);

//===================== Retreival

  FReportObj : TTableStore;
  fListOfRecords : TObjectList;
  FCurrentRecord : TRecord;

  fListOfRecords := fReportObj.GetManyRecords;
  fListOfRecords.count // (is ok)
  FCurrentRecord := fListOfRecords.Items[1]     // ?????????

错误是TObjList TRecord。我是德尔福的新手,所以这可能很简单。我遗漏了什么或不理解什么?谢谢。

您需要使用以下内容将TObject投射到TRecord上:

FCurrentRecord := TRecord(FListOfRecords.Items[1]);
var
  X: TRecord;
  Y: TObject;
begin
  X := TRecord.Create;
  Y := X;
end;
有可能换一种方式,这样你就可以做这样的事情:

FCurrentRecord := TRecord(FListOfRecords.Items[1]);
var
  X: TRecord;
  Y: TObject;
begin
  X := TRecord.Create;
  Y := X;
end;
这是因为编译器知道TRecord是从TObject派生而来的,但在您的代码中,编译器无法知道列表中的TObject实际上是一个TRecord

我建议使用泛型而不是TObjectList。这将创建对象类型的列表。您可以将其用作您的Trecord列表

type
  TRecordList = TObjectList<TRecord>;

要做到这一点,您需要在您的uses子句中包含System.Generics.Collections。

一些人建议您使用泛型来解决您的问题,但我认为使用泛型是没有必要的,因为它们可能会对您的性能造成一点影响,而且它们会带来很多自己的东西,这会增加您的性能EXE大小和应用程序内存使用情况。 相反,您可以通过编写一个索引属性来访问您的内部列表项来轻松解决这个问题,如果TObjectList没有集成到类中,您也可以这样做。 你这样做:

TRecord = class(TObject)
private
  FDescription : Variant;
  FDirectDeposit : Double;
public
  function  GetDescription : Variant;
  function  GetDirectDeposit : Double;
  procedure SetDescription(Value: Variant; DoValidation: Boolean = True);
  procedure SetDirect(Value: Double; DoValidation: Boolean = True);
end;

TTableStore = class(TObject)
private
  FManyRecords : TObjectList;
protected
  //Used to read record from the internal list which has specific index
  function GetRecord(index: Integer): TRecord;
  //Used to write record on the internal list which has psecific index
  procedure SetRecord(index: Integer; Value: TRecord);
public
  //This property alows you to access any Record from your internal list
  property MyRecord[index: Integer]: TRecord read GetRecord write SetRecord;
  //Used for adding new records to your internal list
  procedure AddRecord(MyRecord: TRecord);
  //Used to remove a record with specific index from your internal list
  procedure RemoveRecord(index: Integer);
end;

implementation

procedure TTableStore.AddRecord(MyRecord: TRecord);
begin
    //We simply call TObjectList.Add method and pass reference to the object
    //we wish to add to the list
    FManyRecords.Add(MyRecord);
end;

function TTableStore.GetRecord(index: Integer): TRecord;
begin
    //We read TObjectList item as we normally would and then we typecast it
    //to TRecord class as this is our expected result.
    result := TRecord(FManyRecords[index]);
end;

procedure TTableStore.RemoveRecord(index: Integer);
begin
    //We simply call TObjectList.delete method passing it a index number of
    //item we wish to remove
    FManyRecords.Delete(index);
end;

procedure TForm4.Button1Click(Sender: TObject);
var MyRecord: TRecord;
    Description: Variant;
begin
    Description := 'Test';
    //We create our record
    MyRecord := TRecord.Create;
    //We set description of our record
    MyRecord.SetDescription(Description);
    //We add our record to the internal table
    MyTableStore.AddRecord(MyRecord);
    //We check to see if record which is stored in out internal table on
    //index 0 to see if its description matches our description variable
    if MyTableStore[0].GetDescription = Description then
    begin
        MessageDlg('It works!',mtInformation,[mbOK],0);
    end;
    //Change description to list record directly
    MyTableStore[0].SetDescription('Test2');
    //Test again to see if description got properly updated
    if MyTableStore[0].GetDescription = 'Test2' then
    begin
        MessageDlg('It works!',mtInformation,[mbOK],0);
    end;
end;
这样就避免了使用任何泛型。
遵循我在上面展示的类似方法,您可以从任何内置类转发任何属性或方法(TObjectList实际上是TTableStore类中的内置类)

您正在使用XE2;仿制药是可用的。你真的应该考虑使用<代码> TojjcList,这将使你的生活变得简单多了。你不仅应该使用泛型,而且令人困惑的是,一个类TrordordT记录只用于堆栈溢出。名字被更改以保护无辜者。我只是在OP原始代码上创建了我的示例。我自己也经常避免使用变体。我没有注意到。对不起!正在从此处删除我的评论。。。另外,看看OP的代码,我不在乎性能,因为有一些事情需要解决。