加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Delphi Class TList

发布时间:2020-12-15 09:37:16 所属栏目:大数据 来源:网络整理
导读:我创建了一个简单的类,我将对象保存在通用列表中.我设法让它运作起来.但我不明白为什么这不起作用. for Monster in MonsterList do begin Monster.Free; MonsterList.Remove(Monster); end; 如果我尝试从MonsterList中释放和删除这样的项目,它并没有真正删除
我创建了一个简单的类,我将对象保存在通用列表中.我设法让它运作起来.但我不明白为什么这不起作用.

for Monster in MonsterList do
    begin
      Monster.Free;
      MonsterList.Remove(Monster);
    end;

如果我尝试从MonsterList中释放和删除这样的项目,它并没有真正删除,在我的情况下,名称消失但强度值保持在那里.如果我之后尝试列出MonsterList的内容,我总是剩下一个项目.所以我用谷歌搜索了一下,在堆栈溢出处发现,我很好的解决方案就是简单地计算downto.

另一件事是当我将怪物添加到MonsterList时,我添加3个项目,但是如果我调试我看到MonsterList实际上有0,1,2,3 3是NULL
这只会在我添加全部三个时发生,如果我只添加两个对象,则不会创建最终的NULL指针.这是某种优化的优势吗?

整个守则(不多)

unit MainForm;

interface

uses
  Winapi.Windows,Winapi.Messages,System.SysUtils,System.Variants,System.Classes,Vcl.Graphics,Vcl.Controls,Vcl.Forms,Vcl.Dialogs,Vcl.StdCtrls,Generics.Collections,Generics.Defaults,System.Types;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMonster = class
    private
      fName : string;
      fStrength : integer;
      fisDead : boolean;
    public
      constructor Create(Name : string; Strength : integer);
      destructor Destroy; override;

      property Name : string read fName write fName;
      property Strength : integer read fStrength write fStrength;
      property isDead : boolean read fisDead write fisDead;
  end;

var
  Form1: TForm1;
  MonsterList : TList<TMonster>;
  MonsterInstances : integer = 0;


implementation

{$R *.dfm}

constructor TMonster.Create(Name: string; Strength: integer);
begin

  inc(MonsterInstances);

  fName := Name;
  fStrength := Strength;
  fisDead := false;
end;

destructor TMonster.Destroy;
begin
  dec(MonsterInstances);

  inherited;
end;

procedure TForm1.Button1Click(Sender: TObject);
var Monster : TMonster;
    i : integer;
begin
  MonsterList := TList<TMonster>.Create;

  Memo2.Lines.Add(inttostr(MonsterInstances));

  MonsterList.Add(TMonster.Create('Jill',10));
  MonsterList.Add(TMonster.Create('Jane',1));
  MonsterList.Add(TMonster.Create('Rob',20));

  Memo2.Lines.Add(inttostr(MonsterInstances));

  for Monster in MonsterList do
    begin
      Memo1.Lines.Add(Monster.fName+ ' Strenght '+inttostr(Monster.fStrength)+' IsDead= '+booltostr(Monster.fisDead))
    end;

  MonsterList[1].isDead:=true;

  // not working
  {for Monster in MonsterList do
    begin
      Monster.Free;
      MonsterList.Remove(Monster);
    end; }

  // works
  for i := MonsterList.Count-1 downto 0 do
    begin
      if MonsterList[i].isDead = true then
        begin
          MonsterList[i].Free;
          MonsterList.Delete(i);
          MonsterList.Capacity:=MonsterList.Capacity-1;
        end;
    end;

  Memo1.Lines.Add('Survivors :');

  for Monster in MonsterList do
    Memo1.Lines.Add(Monster.Name+' Strenght '+inttostr(Monster.Strength));


  ShowMessage(inttostr(MonsterInstances));

end;

end.

谢谢!

解决方法

您不能像这样迭代修改列表.而是释放所有成员,然后清除列表.

for Monster in MonsterList do
  Monster.Free;
MonsterList.Clear;

这具有额外的优点,即不调用Remove花费时间搜索该项目.

也许更简单的是使用TObjectList< T>并允许集合管理其成员的生命时间.然后你可以简单地调用Clear,只要OwnsObjects为True,所有成员都将被销毁并清除列表.

至于你的第二个问题,如果添加三个项目,则有索引为0,1和2的项目.没有索引为3的项目.现在,集合内部可能使用过度分配的内部数组.所以私有内部数组可以有索引3.但是内部数组的内容对你来说无关紧要.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读