Delphi Class TList - PullRequest
       4

Delphi Class TList

0 голосов
/ 13 июня 2018

Я создал простой класс, который хранит объекты в общем списке.Мне удалось заставить его работать.Но я не понимаю, почему это не работает.

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

Если я попытаюсь освободить и удалить подобные элементы из списка MonsterList, он на самом деле не удаляет, в моем случае имена исчезли, но Силаценности остались там.Если после этого я пытался составить список содержимого MonsterList, у меня всегда оставался один элемент.Поэтому я немного погуглил и обнаружил, что здесь, в переполнении стека, хорошим решением было бы просто сосчитать до.

Другое дело, когда я добавляю Monsters в 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.

Спасибо!

1 Ответ

0 голосов
/ 13 июня 2018

Вы не можете изменять список, перебирая его таким образом.Вместо этого освободите всех участников, а затем очистите список.

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

Это дает дополнительное преимущество - не вызывать Remove, что тратит время на поиск элемента.

Возможно, проще было бы использовать TObjectList<T> и позволить коллекции управлять временем жизни своих членов.Затем вы можете просто позвонить Clear, и если OwnsObjects равен True, все участники будут уничтожены, а список очищен.

Что касается вашего второго вопроса, если вы добавите три элемента,есть элементы с индексами 0, 1 и 2. Нет элемента с индексом 3. Теперь внутренне коллекция может использовать внутренний массив, который перераспределен.И так, что закрытый внутренний массив может иметь индекс 3. Но содержимое этого внутреннего массива не должно иметь для вас значения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...